Java之同步锁

2年前 (2022) 程序员胖胖胖虎阿
137 0 0

同步代码块

  1. 加锁的为需要被同步的代码

  2. 共享数据,多个线程都需要操作的数据

  3. 同步监视器,即,任何一个对象都可以成为锁。、

    1. 要求:锁必须是唯一的,多线程之间必须共用一把锁
    2. 实现Runnable接口时,我们可以考虑使用this充当同步监视器
    3. 使用Thread继承时我们可以使用类名.class作为同步监视器
    synchronized(同步监视器){
    	需要同步的代码
    }
    

同步方法

  1. 如果操作共享数据的代码完整的声明在一个方法中,我们不妨使用此方法声明同步
  2. 同步方法中仍然涉及到同步监视器,只是不需要我们显示的声明。非静态方法为this,静态方法为类本身
 实现Runnable
public class HeapDemo implements Runnable{

    private int t = 100;
    @Override
    public void run() {
        while (true) {
           show();
        }
    }
    private synchronized void show(){
        if (t > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":" + t);
            t--;
        }
    }
}
class tews{
    public static void main(String[] args) {
        HeapDemo heapDemo = new HeapDemo();

        Thread thread = new Thread(heapDemo);
        Thread thread1 = new Thread(heapDemo);
        Thread thread2 = new Thread(heapDemo);
//        System.err.println(thread.getClass());
//        System.err.println(thread1.getClass());
        thread.setName("线程一");
        thread1.setName("线程二");
        thread2.setName("线程三");
        thread.start();
        thread1.start();
        thread2.start();
    }
}
    
实现继承
public class HeapDemo extends Thread{

    private static int t = 100;
    @Override
    public void run() {
        while (true) {
           show();
        }
    }
    private static synchronized void show(){
        if (t > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ":" + t);
            t--;
        }
    }
}
class tews{
    public static void main(String[] args) {
    
    +++++++++++++++++++++++++++++++++++++++++++++++++
        HeapDemo heapDemo = new HeapDemo();
        HeapDemo heapDemo1 = new HeapDemo();
        HeapDemo heapDemo2 = new HeapDemo();
	 +++++++++++++++++++++++++++++++++++++++++++++++++ 
        
        
        heapDemo.setName("线程一");
        heapDemo1.setName("线程二");
        heapDemo2.setName("线程三");
        heapDemo.start();
        heapDemo1.start();
        heapDemo2.start();
    }
}

Lock

​ jdk5.0开始,Java提供了更强大的线程同步机制——通过显式定义同步锁对象实现同步,同步锁使用Lock对象充当。

java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具,锁提供了对共享资源的独立访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前应先获得Lock对象。

ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,在实现线程安全控制中,比较常用的是ReentrantLock,可以显式加锁,释放锁

public class HeapDemo implements Runnable{

    private  int t = 100;
    ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true) {
            try {
                lock.lock();
                if (t > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + ":" + t);
                    t--;
                }else{
                    break;
                }
            }finally {
                lock.unlock();
            }
        }
    }


}
class tews{
    public static void main(String[] args) {
        
        HeapDemo heapDemo = new HeapDemo();

        Thread thread = new Thread(heapDemo);
        Thread thread1 = new Thread(heapDemo);
        Thread thread2 = new Thread(heapDemo);
        thread.setName("线程一");
        thread1.setName("线程二");
        thread2.setName("线程三");
        thread.start();
        thread1.start();
        thread.start();
    }
}

synchronized与Lock的对比

  1. Lock是显式锁(手动打开和关闭锁),synchronized是隐式锁,出了作用域自动释放
  2. Lock只有代码块锁,synchronized有代码块锁和方法锁
  3. 使用Lock锁,JVM将花费较少的时间来调度线程,性能更好,并且提供了更多的子类,有良好的扩展性

sleep()和wait()的异同

相同点:一旦执行,线程将进入阻塞状态

不用点:

  1. 方法声明的位置不同,Thread方法中声明sleep(),Object中声明wait()
  2. 调用的要求不同。sleep()可以在任何情境下调用,wait()必须在同步代码块或同步方法中。(notify()/notifyAll()也是)
  3. 关于释放同步监视器。如果两个方法都在同步代码块或同步方法中,sleep()不释放锁,wait()释放锁
版权声明:程序员胖胖胖虎阿 发表于 2022年9月5日 上午1:16。
转载请注明:Java之同步锁 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...