java多线程同步synchronized_复习基础-Java多线程synchronized同步

synchronized是针对对象的隐式锁使用的,注意是对象!

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

public class MyObject {

synchronized public void methodA() {

//do something....

}

}

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

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

上面的代码也可以写成这样:

public class MyObject {

public void methodA() {

synchronized(this){

//do something....

}

}

二、特点

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

public class MyObject {

synchronized public void methodA() {

//do something....

}

synchronized public void methodB() {

//do some other thing

}

}

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

public class ThreadA extends Thread {

private MyObject object;

//省略构造方法

@Override

public void run() {

super.run();

object.methodA();

}

}

线程A执行methodA()

public class ThreadB extends Thread {

private MyObject object;

//省略构造方法

@Override

public void run() {

super.run();

object.methodB();

}

}

线程B执行methodB()

public class ThreadB extends Thread {

private MyObject object;

//省略构造方法

@Override

public void run() {

super.run();

object.methodB();

}

}

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

三、结论

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

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

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

public class MyObject {

private String userName = "b";

private String passWord = "bb";

synchronized public void methodA(String userName, String passWord) {

this.userName = userName;

try{

Thread.sleep(5000);

}catch(InterruptedException e){

}

this.passWord = passWord;

}

synchronized public void methodB() {

System.out.println("userName" + userName + ": " + "passWord" + passWord);

}

}

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

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

如果methodB()没有用synchronized 修饰,线程A在调用methodA()执行到第7行,更改了用户名,因某种原因(比如在第9行睡眠了)放弃了CPU。

此时,如果线程B去执行methodB(),那么读取到的用户名是线程A更改了的用户名("a"),但是密码却是原来的密码("bb")。因为,线程A睡眠了,还没有来得及更改密码。

但是,如果methodB()用synchronized修饰,那么线程B只能等待线程A执行完毕之后(即改了用户名,也改了密码),才能执行methodB读取用户名和密码。因此,就避免了数据的不一致性而导致的脏读问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值