多线程——线程同步互斥(synchronized)

java中,线程互斥是为了保证在同一时刻,只有一个线程在访问一段特定的代码或者一个特定的变量。

 

看一个多线程使用同一个对象操作引起的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.model.elgin.thread;

public   class TestThread4 {
  
public   static   void main( String [] args) {
       init();
   } 

  
private   static   void   init(){
        
       
final PrintString ps= new PrintString();
       
//开启2个线程,分别使用同一个ps对象来打印不同的字符串
        new Thread( new Runnable() {
            
            @Override
           
public   void run() {
               
while (true){    
                    ps.print(
"Chinajiangsuchangzhou" );
                }
            }
        
        }).start();
        
       
new Thread( new Runnable() { 
            @Override
           
public   void run() {
               
while (true){    
                    ps.print(
"Americanlalala" );     
                }
            }
        }).start();
    }
}

class PrintString{
   
//按单个字符打印字符串
    public   void print( String name){    
         
for ( int i = 0 ; i < name.length(); i++) { 
              System.out.print(name.charAt(i)); 
          }
          System.out.println();     
    }
}

这时候,可以从结果中偶尔发现这样的输出:

image

我们发现,2个线程中的不同的字符串内容出现了错乱,这就是在多个线程同时访问同一个资源(此处为ps对象)时出现的问题。

那么这个问题该如何处理呢?

我们可以通过对多个线程访问的公共方法或者代码块加锁来实现,保证在同一时刻只有一个线程在访问处理资源。

有2种方式来实现锁:

1)、在PrintString类的print方法上增加synchronized关键字来给方法加锁。在已有线程在调用此方法的时候,其它的线程不能调用它。

2)、通过同步代码块来给一段代码加锁,修改如下:

1
2
3
4
5
6
7
8
9
10
11
class PrintString{
   
//按单个字符打印字符串
    public   void   print( String name){
      
synchronized ( this ){
          
for ( int i = 0 ; i < name.length(); i++) {    
               System.out.print(name.charAt(i));    
           }
           System.out.println();
       }    
    }
}

修改过后,再次运行,上述问题不再出现。

总结:

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

注意:要互斥,必须让锁是同一把。以上的demo中,两个线程都用的是同一个new出来的ps对象,所以是同一个对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值