关于Java多线程的synchronized的问题

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

五、以上规则对其它对象锁同样适用.

举例说明:

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。 
package  ths; 

public   class  Thread1  implements  Runnable 
public void run() 
synchronized(this
for (int i = 0; i  < 5; i++
System.out.println(Thread.currentThread().getName() 
+ " synchronized loop " + i); 
}
 
}
 
}
 
public static void main(String[] args) 
Thread1 t1 
= new Thread1(); 
Thread ta 
= new Thread(t1, "A"); 
Thread tb 
= new Thread(t1, "B"); 
ta.start(); 
tb.start(); 
}
 
}
 

结果: 

synchronized  loop  0  
synchronized  loop  1  
synchronized  loop  2  
synchronized  loop  3  
synchronized  loop  4  
synchronized  loop  0  
synchronized  loop  1  
synchronized  loop  2  
synchronized  loop  3  
synchronized  loop  4  

 二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

 

package  ths; 

public   class  Thread2 
public void m4t1() 
synchronized(this
int i = 5
while( i--  > 0
System.out.println(Thread.currentThread().getName() 
+ " : " + i); 
try 
Thread.sleep(
500); 
}
 catch (InterruptedException ie) 
}
 
}
 
}
 
}
 
public void m4t2() 
int i = 5
while( i--  > 0
System.out.println(Thread.currentThread().getName() 
+ " : " + i); 
try 
Thread.sleep(
500); 
}
 catch (InterruptedException ie) 
}
 
}
 
}
 
public static void main(String[] args) 
final Thread2 myt2 = new Thread2(); 
Thread t1 
= new Thread( 
new Runnable() 
public void run() 
myt2.m4t1(); 
}
 
}
"t1" 
); 
Thread t2 
= new Thread( 
new Runnable() 
public void run() 
myt2.m4t2(); 
}
 
}
"t2" 
); 
t1.start(); 
t2.start(); 
}
 
}
 

结果: 

t1 : 
4  
t2 : 
4  
t1 : 
3  
t2 : 
3  
t1 : 
2  
t2 : 
2  
t1 : 
1  
t2 : 
1  
t1 : 
0  
t2 : 
0  

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

// 修改Thread2.m4t2()方法: 

public   void  m4t2() 
synchronized(this
int i = 5
while( i--  > 0
System.out.println(Thread.currentThread().getName() 
+ " : " + i); 
try 
Thread.sleep(
500); 
}
 catch (InterruptedException ie) 
}
 
}
 
}
 

}
 

结果: 

t1 : 
4  
t1 : 
3  
t1 : 
2  
t1 : 
1  
t1 : 
0  
t2 : 
4  
t2 : 
3  
t2 : 
2  
t2 : 
1  
t2 : 
0  

四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。

// 修改Thread2.m4t2()方法如下: 

public   synchronized   void  m4t2() 
int i = 5
while( i--  > 0
System.out.println(Thread.currentThread().getName() 
+ " : " + i); 
try 
Thread.sleep(
500); 
}
 catch (InterruptedException ie) 
}
 
}
 
}
 

结果: 

t1 : 
4  
t1 : 
3  
t1 : 
2  
t1 : 
1  
t1 : 
0  
t2 : 
4  
t2 : 
3  
t2 : 
2  
t2 : 
1  
t2 : 
0  

五、以上规则对其它对象锁同样适用:

package  ths; 

public   class  Thread3 
class Inner 
private void m4t1() 
int i = 5
while(i--  > 0
System.out.println(Thread.currentThread().getName() 
+ " : Inner.m4t1()=" + i); 
try 
Thread.sleep(
500); 
}
 catch(InterruptedException ie) 
}
 
}
 
}
 
private void m4t2() 
int i = 5
while(i--  > 0
System.out.println(Thread.currentThread().getName() 
+ " : Inner.m4t2()=" + i); 
try 
Thread.sleep(
500); 
}
 catch(InterruptedException ie) 
}
 
}
 
}
 
}
 
private void m4t1(Inner inner) 
synchronized(inner) //使用对象锁 
inner.m4t1(); 
}
 
}
 
private void m4t2(Inner inner) 
inner.m4t2(); 
}
 
public static void main(String[] args) 
final Thread3 myt3 = new Thread3(); 
final Inner inner = myt3.new Inner(); 
Thread t1 
= new Thread( 
new Runnable() 
public void run() 
myt3.m4t1(inner); 
}
 
}
"t1" 
); 
Thread t2 
= new Thread( 
new Runnable() 
public void run() 
myt3.m4t2(inner); 
}
 
}
"t2" 
); 
t1.start(); 
t2.start(); 
}
 
}
 

结果: 

尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。 

t1 : Inner.m4t1()
= 4  
t2 : Inner.m4t2()
= 4  
t1 : Inner.m4t1()
= 3  
t2 : Inner.m4t2()
= 3  
t1 : Inner.m4t1()
= 2  
t2 : Inner.m4t2()
= 2  
t1 : Inner.m4t1()
= 1  
t2 : Inner.m4t2()
= 1  
t1 : Inner.m4t1()
= 0  
t2 : Inner.m4t2()
= 0  

现在在Inner.m4t2()前面加上synchronized: 

private   synchronized   void  m4t2() 
int i = 5
while(i--  > 0
System.out.println(Thread.currentThread().getName() 
+ " : Inner.m4t2()=" + i); 
try 
Thread.sleep(
500); 
}
 catch(InterruptedException ie) 
}
 
}
 
}
 

结果: 

尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方法。 

t1 : Inner.m4t1()
= 4  
t1 : Inner.m4t1()
= 3  
t1 : Inner.m4t1()
= 2  
t1 : Inner.m4t1()
= 1  
t1 : Inner.m4t1()
= 0  
t2 : Inner.m4t2()
= 4  
t2 : Inner.m4t2()
= 3  
t2 : Inner.m4t2()
= 2  
t2 : Inner.m4t2()
= 1  
t2 : Inner.m4t2()
= 0   

总结:记住一句话
见到synchronized就该说“在什么对象上锁住了哪块代码”
synchronized永远有两个要素,一个是什么对象,或者说什么锁,第二个是哪部分代码

public synchronized function1(){
num++;
}

等同于

public function1()}{
synchronized(this){
num++;
}
}

就是在this这个对象上加锁

他不但和
public synchronized function2(){
num--;
}
同步,还和
public function3(){
System.out.println("");
synchronized(this){
num++;
}
}
同步

更有趣的是,如果function1,function2,function3都是一个对象obj的方法,如果另外一个类使用该对象,那么它还和如下代码同步

class Other{
...

public void testSynchronized(){
synchronized(obj){
...
}

...
}


总而言之,只要见到synchronized就问一句“在什么对象上锁住了哪块代码”,如果对象相同,就是同步的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值