Java并发编程(三)——synchronized

Java并发编程(三)——synchronized

一,概述

  synchronized关键字是Java中用来控制线程并发访问的基础机制,利用synchronized来控制一块代码同一时间只能有一个线程访问,其它线程等待,相当于加锁。
  synchronized提供的是互斥锁,仅能实现对资源的互斥访问,而concurrent.lock不仅有互斥锁,还有读写锁。把读锁和写锁分开,写锁相当于互斥锁,而读锁是共享的,可以让多线程同时读,以提高性能。
  synchronized关键字是不能继承的。

二,用法

  synchronized使用方式不同会对代码产生不同的影响,主要使用方式有以下几种:

1,synchronized修饰方法
public synchronized void method(){
   //  
}

  这是一个同步方法,使用的是对象锁,锁是该方法的调用者,就是当前对象this,这时synchronized锁定的就是调用这个同步方法对象。
  也就是说,当同一个对象p1在多个不同的线程中调用这个方法时,他们之间会形成互斥,因为它们的锁都是p1这个对象锁。同时如果该对象中有多个同步方法,则当一个线程执行该对象中的一个synchronized方法,则该对象中其它同步方法也被锁住,不允许别的线程执行。但是同一个类的另一对象p2却不受p1锁的影响,因为p2对象中的同步方法使用的锁是p2。程式在这种情形下很可能摆脱同步机制的控制,造成数据混乱,可以通过单例模式来解决。
  上边的示例代码等同于如下代码:

public void method()   {   
    synchronized (this)      
    {   
       // 
    }   
}  

  上面的代码使用this作为锁,也就是使用当前对象作为锁,也是对象锁。

2,synchronized修饰代码块
public void method(Object o) {   
   synchronized(o)   
   {   
        //..   
   }   
}  

  这时,采用的也是对象锁,但锁不再是当前对象,而是对象o,哪个线程拿到这个对象锁就能够运行它所控制的那段代码。一般只需创建一个特别的instance变量来充当锁,这样最为节省资源:

private byte[] lock = new byte[0]; 
public void method(){   
    synchronized(lock) 
    { 
       // 
    }
}   
3,synchronized修饰static函数
public class Foo {   
    public synchronized static void method1(){   
        //   
    }   
    public void method2(){   
        synchronized(Foo.class)   
        //
    }   
}  

  这两个同步方法都利用类作为锁,也就是类锁,而不再是由某个具体对象了。

三,总结

假设有类P,及其两个对象p1和p2,并发线程t1和t2,有如下结论:
  使用synchronized(this)或synchronized方法时(即使用类P的对象锁时)

1,线程t1和t2并发访问同一个对象p1的一个具有对象锁的同步代码块或方法时,同一时间只能有一个线程得到执行,另一个线程必须等待当前线程执行完`这个代码块或方法`以后才能执行`该代码块或方法`;
2,然而,当t1访问p1的一个具有对象锁的同步代码块或方法时,t2仍然可以访问p1的其它不是用p1作为锁的同步代码块或方法。
3,尤其关键的是,当t1访问p1的一个具有对象锁的同步代码块或方法时,t2对p1中所有其它用p1作为锁的同步代码块或方法的访问将被阻塞。

注:上面说的“具有对象锁的代码块”,都是指具有`当前类的对象`作为锁的代码块,而不是其它类的对象。

  使用synchronized(P.class)或synchronized static方法时(即使用类锁时)

1,t1访问p1的一个具有类锁的同步代码块或方法时,其他线程对p1的所有具有当前类锁的同步代码块或的访问将被阻塞;
2,t1访问类P的一个具有类锁的同步代码块或方法时,其他线程对类P的所有具有类锁的同步代码块或方法的访问将被阻塞。
3,t1访问类P的一个具有类锁的同步代码块或方法时,其他线程对类P的所有实例对象(如p1,p2)的所有具有类锁的同步代码块或方法的访问将被阻塞。

具体实例可参见https://github.com/ricklkl/demo/tree/master/src/main/java/com/rick/demo/synchron
  综上所见,是否被阻塞的关键是锁是否被占用,对象锁尤其如此;而类锁的级别更高,所有类的对象以及类,都共用一个类锁。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值