线程通信 使用Synchronized或Lock

90 阅读1分钟

Lock与Synchronized区别

Lock不是JAVA内置,Synchronized是Java关键字,是内置的。

Synchronized不用手动释放锁,Lock需要手动释放锁,否则有可能造成死锁

Lock可以让等待锁的线程众多,Synchronized不行

Lock可以知道有没有成功获取锁,Synchronized不行

Lock可以提高多个线程进行读操作效率

线程通信

Synchronized常与wait(),notifyAll()连用,Lock常与awit(),signalAll()连用

private Lock lock = new ReentrantLock();
Condition condition=lock.newCondition();
//上锁
lock.lock();
//判断
while(){
   condition.await();
}
//干活

//通知
condition.signalAll();

//解锁 最好写在finally里保证肯定执行
lock.unlock(); 

//线程通信 方法一: 
//可能出现虚假唤醒,
while(){
  this.wait();//唤醒后从等待的地方开始,所以this.wait()最好加在while()之间
 }
this.notifyAll();

//方法二:用Lock
while(){
   condition.await();//唤醒后从等待的地方开始,所以this.wait()最好加在while()之间
 }
condition.signalAll();

案例

/*打印A一次 B两次 C三次
循环十次*/

public class Print {
    private int flag = 1;
    private Lock l = new ReentrantLock();
    Condition c1 = l.newCondition();
    Condition c2 = l.newCondition();
    Condition c3 = l.newCondition();

    public void A(int loop) throws InterruptedException {
        // Lock l = new ReentrantLock();
        l.lock();
        while (flag != 1) {
            c1.await();
        }
        System.out.println("A"+loop);
        flag = 2;
        c2.signalAll();
        l.unlock();
    }

    public void B(int loop) throws InterruptedException {
        // Lock l = new ReentrantLock();
        l.lock();
        while (flag != 2) {
            c2.await();
        }
        for (int i = 0; i < 2; i++) {
            System.out.println("B"+loop);

        }
        flag = 3;

        c3.signalAll();
        l.unlock();
    }

    public void C(int loop) throws InterruptedException {
        // Lock l = new ReentrantLock();
        l.lock();
        while (flag != 3) {
            c3.await();
        }
        for (int i = 0; i < 3; i++) {
            System.out.println("C"+loop);

        }
        flag = 1;
        c1.signalAll();
        l.unlock();
    }

public static void main(String[] args) {
    Print p = new Print();
    new Thread(() -> {
        try {
            for (int i = 1; i <10 ; i++) {
                p.B(i);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }).start();
    new Thread(() -> {
        try {
            for (int i = 1; i <10 ; i++) {
                p.C(i);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }).start();
    new Thread(() -> {
        try {
            for (int i = 1; i <10 ; i++) {
                p.A(i);
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }).start();


}