小白的Java之路--java并发编程之synchronized初学

synchronized初学

基础总结(what)

接触java开发已经将近一年,一直以来只是单纯的运用公司提供的框架,按照固定的模式去实现业务功能。如今回想,想要在java开发上更进一步,于是首先想理解掌握java并发编程

想学习并发编程,就算我什么都不了解也是知道synchronized关键字的,其作用是为了控制多个线程访问共享资源时的并发安全问题,通过资料收集了解到:

1. 当两个及以上的线程访问同一个对象的同一个synchronized同步代码块时,仅能有一个线程能竞争到改资源得到执行,另外一个线程必须等到当前执行线程完成之后,继续竞争改同步代码块的执行权;

2. 当有一个线程正在访问一个object对象的一个synchronized同步代码块时,其他线程对该object对象的所有其他synchronized代码块访问将会被阻塞;

3. 一个线程任务在执行时可以多次获取同一个对象锁,如:一个线程方法在一个对象上调用了一个同步方法,而该同步方法又调用了该对象本身的另外的同步对象方法。此时,jvm会跟踪对象被加锁的次数,一个对象被解锁一次,对象锁的数量-1,每当任务中给每次在对象上获得锁的时候,锁的数量就+1;(可以知道只有在开始竞争到锁成功的线程任务才能多次获得锁),因为每当任务离开一次synchronized方法时,锁的数量就减去1,逐次递减,直到锁的数量变为0,该资源被完全释放,其他任务可以开始竞争使用此资源;

何时使用(when)

 Brian同步规则:如果你正在"写"一个变量,它可能接下来将被另一个线程"读"取,或者正在"读"取一个上一次已经被另一个线程"写"过的变量,那么你必须使用同步,并且,"读"/"写"线程都必须用相同的监视器锁同步。

注意:每个访问临界共享资源的方法都必须被同步,否则它们不会正确工作。

如何使用(how)

synchronized 关键字,它包括两种用法: synchronized 方法synchronized 块
  • synchronized 方法:
public synchronized void countNum(int n){}

特定对象所有synchronized方法共享同一个锁,这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized)。 

扫描二维码关注公众号,回复: 6722715 查看本文章

  不光如此,静态方法也可以声明为 synchronized ,以控制其对类的静态成员变量的访问。

public static synchronized void countNum(int n){}

synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率。

  典型地,若将线程类的方法 run() 声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。

  • synchronized 块:
synchronized(SyncObject.Class) { 
    //允许访问控制的代码 
} 

亦可写成如下格式,this--指的就是当前这个类

synchronized(this) { 
    //允许访问控制的代码 
} 

synchronized 块中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

  在使用synchronized 块的时候,一定要遵循Brian同步规则,并对每个访问临界共享资源的方法都进行同步。

参考:

https://blog.csdn.net/yuan1013922969/article/details/54971632

猜你喜欢

转载自www.cnblogs.com/EtherealWind/p/11131264.html
今日推荐