Java多线程之Synchronized关键字

所谓对象锁,就是就是synchronized 给某个对象加锁。关于 对象锁 可参考:这篇文章 

二,分析

synchronized可以修饰实例方法,如下形式:

1 public class MyObject { 2 3 synchronized public void methodA() { 4 //do something.... 5 }

这里,synchronized 关键字锁住的是当前对象。这也是称为对象锁的原因。

为啥锁住当前对象?因为 methodA()是个实例方法,要想执行methodA(),需要以 对象.方法() 的形式进行调用(obj.methodA(),obj是MyObject类的一个对象,synchronized就是把obj这个对象加锁了)。

上面代码也可写成这样:

1 public class MyObject { 2 3 public void methodA() { 4 synchronized(this){ 5 //do something.... 6 } 7

三,特点

使用synchronized关键字同步一个明显的特点是:MyObject类中定义有多个synchronized修饰的实例方法时,若多个线程拥有同一个MyObject类的对象则这些方法只能以同步的方式执行。即,执行完一个synchronized修饰的方法后,才能执行另一个synchronized修饰的方法。

如下:

1 public class MyObject { 2 3 synchronized public void methodA() { 4 //do something.... 5 } 6 7 synchronized public void methodB() { 8 //do some other thing 9 } 10 }

MyObject类中有两个synchronized修饰的方法。

1 public class ThreadA extends Thread { 2 3 private MyObject object; 4 //省略构造方法 5 @Override 6 public void run() { 7 super.run(); 8 object.methodA(); 9 } 10 }

线程A执行methodA()

public class ThreadB extends Thread { private MyObject object; //省略构造方法 @Override public void run() { super.run(); object.methodB(); } }

线程B执行methodB()

public class Run { public static void main(String[] args) { MyObject object = new MyObject(); //线程A与线程B 持有的是同一个对象:object ThreadA a = new ThreadA(object); ThreadB b = new ThreadB(object); a.start(); b.start(); } }

由于线程A和线程B持有同一个MyObject类的对象object,尽管这两个线程需要调用不同的方法,但是必须是同步的,比如:线程B需要等待线程A执行完了methodA()方法之后,它才能执行methodB()方法。

四,结论

从上可以看出,本文中讲述的 synchronized 锁的范围是整个对象。如果一个类中有多个synchronized修饰的同步方法,且多个线程持有该类的同一个对象(该类的相同的对象),尽管它们调用不同的方法,各个方法的执行也是同步的。

如果各个同步的方法之间没有共享变量,或者说各个方法之间没有联系,但也只能同步执行,这会影响效率。

五,应用--使用synchronized避免 因数据不一致性而导致读脏数据的情况

如下示例:

1 public class MyObject { 2 3 private String userName = "b"; 4 private String passWord = "bb"; 5 6 synchronized public void methodA(String userName, String passWord) { 7 this.userName = userName; 8 try{ 9 Thread.sleep(5000); 10 }catch(InterruptedException e){ 11 12 } 13 this.passWord = passWord; 14 } 15 16 synchronized public void methodB() { 17 System.out.println("userName" + userName + ": " + "passWord" + passWord); 18 } 19 }

methodA()负责更改用户名和密码。在现实中,一个用户名对应着一个密码。。。

methodB()负责读取用户名和密码。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/eb781872d11bc9c6d7065b26a9d72001.html