对synchronized关键字的总结

前段时间学了线程那章,对synchronized的关键字开始还搞得不太清楚,现在摸了几天总算大致了解了,现在用个人的理解和语言总结一下。


1.被synchronized作用的语句块,在线程调用执行时,这个语句块成为一个原子操作而不可分,避免出现脏数据(原子操作只是个比喻,中间还是能停止的,而脏数据是多线程为什么需要同步的根本原因),不能从运行到中间停止被别的操作同样语句块或者需要同样的对象锁的进程插进来运行。


2. synchronized(Object o),包括(this),更像是这个作用生效时,必须要满足的一个条件比如有个方法被一个线程启动,其线程的语句块里有一个synchronized(Object o){...},你想让语句块{...}执行,你必须有有对象o的锁,才能运行,因此,为了达成同步效果,往往随便造一个对象o就能达到锁(比如造一个对象lock,或者一个空的字符串)的目的,即同步的目的,此时除非语句块{...}释放了o的锁,如使用wait()语句,其他线程才有可能拿到o的锁,然后执行{...},这就达成了一个简单的同步手段。

3. 当synchronized修饰一个方法体synchronized a method(){...},或者说,也就是等价a method(){ synchronized(this){...}} 时(当然后者的粒度可以比前者的缩小一点,不一定包含整个方法体,只要包含需要同步的地方就行了),其实也一样,你要调用语句块{...}时,你必须要拿到this的锁,那this是指哪个对象呢?那就是调用这个方法或者这段语句块的对象


比如


class A{
int i=0;
public void add(){ //等价于public void add(){synchornized(this){i++};
i++;
try{
Thread.sleep(2);
}catch(Exception e){}
}


public synchronized void minus(){
i--;
try{
Thread.sleep(2);
}catch(Exception e){}

}

}


class Add implements Runnable{
A a;
Add(A a){

this.a = a;

}

public void run(){
a.add();

}

}



class Minus implements Runnable{
A a;
Minus(A a){

this.a = a;

}

public void run(){
a.minus();

}

}



public class MAIN{
public static void main(String[] args){
A a=new A();
Thread t1=new Thread(new Add(a));
Thread t2=new Thread(new Add(a));
Thread t3=new Thread(new Minus(a));
Thread t4=new Thread(new Minus(a));
t1.start();
t2.start();
t3.start();
t4.start();
try{
Thread.sleep(100);
}catch(Exception e){
}
System.out.println(a.i);
}

}



这这时候,add()和minus()都是同步的,因为尽管t1,t2是两个对象,他们的run方法都是执行同一个对象a的方法而a的两个方法,都需要拥有调用这个方法的对象的锁,这个对象,当然就是this对象了(此例中是对象a),那么当有一个进程在启动这个run方法时,run方法进而执行a的需要锁的方法,比如a.add()时,说明他已经拿到了a的对象锁,而其他的线程就要等待,所以说实质上同2是一样的。除非你又new了一个A b=new A(); Thread t5=new Thread(new Add(b));这个时候t3调用方法的this指的是b,与a无关。另外,如果我在Class A中又加了一个方法public void multiple(){a=a*2;},不加锁,然后写了一个Multiple类继承Runnable,又开了一个线程去调用a对象的multiple方法,由于这个方法不需要锁就能用,所以跟之前的线程是不同步的,不受加锁的影响,这就为什么我说synchornized(Object o)像是一个条件满足语句,满足它才能执行,当锁被别人独占时,只有等待。


4.最后一种就是对整个类加锁,那就是说你要调用这个类的(应该是指static方法)方法,你必须拿到这个类锁,这是无视某个具体对象的。这里就不谈这个了。


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


最后在针对之前说的第2点补充一下,第2点说到了“ synchornized(Object o),包括(this),更像是这个作用生效时,必须要满足的一个条件”,这个条件是针对这个线程来说的,只要这个线程竞争到了这个条件,那么在synchronized的语句块,若又调用其他的方法,这个方法也要这个锁,那么只要还在这个线程里,就没问题。
比如,在上面的代码中,在类Add的run()方法里,加了个锁synchornized(a){a.add();} ,但是运行a.add();也需要对象a的锁,我最初按照自己的理解,此时锁被Add的一个实例拿到了,那么对象a要运行add()方法就不行了。但做实验后发现我错了,因为这个条件是针对一个线程来说的,在java的实现中,是分配一个监视器到一个线程的,所以说只要是在一个线程,就没问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值