JAVA并发学习笔记

ZHLH 2019年11月15日 85次浏览

synchronized锁实例方法的时候,只锁住当前对象,不同对象(即使两个对象是同属于同一个类的)之间不会相互影响。
synchronized锁实例方法适合,会锁住类对象,类对象与实例对象相互独立,互不影响。

一个日本作者-结成浩的《java多线程设计模式》有这样的一个列子:

pulbic class Something(){  
    public synchronized void isSyncA(){}  
    public synchronized void isSyncB(){}  
    public static synchronized void cSyncA(){}  
    public static synchronized void cSyncB(){}  
}  

那么,假如有Something类的两个实例x与y,那么下列各组方法被多线程同时访问的情况是怎样的?

a. x.isSyncA()与x.isSyncB()   
b. x.isSyncA()与y.isSyncA()  
c. x.cSyncA()与y.cSyncB()  
d. x.isSyncA()与Something.cSyncA()  

这里,很清楚的可以判断:
a,都是对同一个实例(x)的synchronized域访问,因此不能被同时访问。(多线程中访问x的不同synchronized域不能同时访问)
如果在多个线程中访问x.isSyncA(),因为仍然是对同一个实例,且对同一个方法加锁,所以多个线程中也不能同时访问。(多线程中访问x的同一个synchronized域不能同时访问)
b,是针对不同实例的,因此可以同时被访问(对象锁对于不同的对象实例没有锁的约束)
c,因为是static synchronized,所以不同实例之间仍然会被限制,相当于Something.isSyncA()与 Something.isSyncB()了,因此不能被同时访问。
那么,第d呢?,书上的 答案是可以被同时访问的,答案理由是synchronzied的是实例方法与synchronzied的类方法由于锁定(lock)不同的原因。
个人分析也就是synchronized 与static synchronized 相当于两帮派,各自管各自,相互之间就无约束了,可以被同时访问。

  • 如果两个线程同时synchronized一个对象,那么两个线程都会因为这个对象而互斥。

微信图片_20191115220028.png

## 为什么wait和notify要在同步块中?
因为如果不放在同步块里面(不加锁),会出现lost wake up问题:
20190412142433326.jpg
消费者线程需要等待直到生产者线程完成一次写入操作。生产者线程需要等待消费者线程完成一次读取操作。假设没有应用Synchronized关键字,当消费者线程执行wait操作的同时,生产线线程执行notify,生产者线程可能在等待队列中找不到消费者线程。导致消费者线程一直处于阻塞状态。那么这个模型就要失败了。所以必须要加Synchronized关键字。