java 多线程 synchronized 入门博文二

来源:互联网 发布:wamp mysql 无法启动 编辑:程序博客网 时间:2024/05/21 13:20

在阅读完上一篇博文之后,思考几个问题。

1、什么是synchronized

话有点绕,请耐心一点。

《同步》:一对调用者和被调用者,调用者需等待被调用方法执行完毕,再继续。

如果被调用方法又被其他的调用者调用,那么可能会影响之前的调用者得到的结果,

所以要在被调用方法执行完毕之前,阻塞其他调用者。

《阻塞》:前面的车占道堵着我,我的车又堵着别人。线程被已得到锁的正在执行的线程阻塞,

什么时候等到锁什么时候开始执行。原因是竞争稀少资源。

《互斥》:你,我,他互斥,要么你,要么我,要么他,资源拥有者的唯一性,排他性。

前面可以有多个车挡着我,但是占有锁的线程某一时刻只有一个。目的是保证没有人影响我,我也不影响别人。

2、为什么用synchronized

再来看为什么用synchronized(同步)这个单词来做java多线程并发的修饰符。

声明这段代码的执行方式是同步的,也就是要保证这次调用的结果是这次调用的过程产生的,

不被其他线程干扰,所以要阻塞其他线程,而且是互斥的,同时只有一个线程在执行被同步的代码段。

互斥保证正在执行的线程间不互相干扰,因为是互斥的,只有一个线程在执行,没有其他的。

所以,同步,阻塞,互斥这三个词,在并发这里是合作说明一个事。

3、如何使用synchronized

synchronized method(){

   ...

}

 

method(){

   synchronized(this){

      ...

   }

}

 

显然synchronized代码段的方式比加在方法声明处的方式要精确,为什么还有在方法处声明synchronized的方式呢?

个人觉得就是省事,说白了就是给一个简易的办法,来降低使用的门槛。设计的时候总要难易搭配。

4、synchronized与锁

synchronized是声明这段代码要以同步的方式来执行

锁是达到并发同步要求的互斥性和阻塞性的手段

 

method(){

   synchronized(this){

      ...

   }

}

这里的this就是java里this关键字表示的对象,也就是当前的这个含有同步代码段的类的这个实例,

这个锁是一个对象,可以是当前对象,也可以是其他对象,也可以是class。

无非是为了保证阻塞和互斥,用谁当锁都一样,所以不限制。

  • 对于同步方法,锁是当前实例对象。
  • 对于静态同步方法,锁是当前对象的Class对象。
  • 对于同步方法块,锁是Synchonized括号里配置的对象。

class A{

method1(){

   synchronized(this){

      ...

   }

}

method2(){

   synchronized(this){

      ...

   }

}

method3(){

}

method4(){

}

}

=========================================================

类A的method1和method2有同步代码段,method3和method4是普通非同步方法

类A有两个实例a1和a2

=========================================================

如果线程调用的是a1的method1或method2.那么锁就是a1本身

如果线程调用的是a2的method1或method2.那么锁就是a2本身

这是两把不同的锁,互相之间没有关系,既不阻塞,也不互斥

 

调用同一对象的synchronized代码段,会阻塞这个对象的其他synchronized代码段,不会阻塞这个对象的非同步代码段

由此看出,锁(一个对象)就是为了保证互斥和阻塞,那么我们可以选择经济一点的对象作为锁。

 

一段同步代码上的锁,这把锁同一时刻只能被一个线程占有,保证这段代码同一时刻只能被一个线程执行。

一把锁,就是一个对象,这个对象可能有多个同步代码段,如果这个对象的某个同步代码段被执行,则这把锁被占用,则这个对象上的其他同步代码不能被执行,否则说明这把锁被其他线程占用,不满足锁的互斥性。这里锁被占用=被锁住的代码在执行。当然也可以选任意一个对象作为锁,这个对象上可以根本没有同步代码段。锁和被锁住的代码段是两回事!

=========================================================

5、synchronized优化

method(){

   synchronized(this){

      ...

   }

}

对于这种同步方式

个人理解有两个地方可以优化,

一是选择的锁,这个作为锁的对象规模越小越好

二是synchronized包住的代码段越短越好

倒不是说抽象的层次越高含有的代码越少,如果还调用其他方法,那其实代码量不小

这里的主要意思是,把不必要的代码剔出去,什么叫必要,就是确实要加同步控制的。

什么叫同步控制,就是这次调用的结果仅是这次调用的过程产生的结果,

如果被同步的代码段里含有一些代码,这些代码即使被其他线程调用也不会影响正在执行的线程,

那这些代码就可以提出来,否则会增加不必要的阻塞。

所以synchronized要出现在合适的抽象级别上,包住必要的阻塞代码。

原创粉丝点击