关于synchronized关键字的一点学习体会

 最近看视频学习java,这几天对synchronized关键字一直很迷惑,今天自己写了几个小程序验证,算是明白了在方法前加synchronized的作用

 在方法前加synchronized关键字的效果:当同一个对象作为参数创建的不同线程调用带有synchronized方法时,存在互斥等待,也就是说用同一个对象产生的不同线程执行该方法时,他们之间必须只有一个可以执行,其他的必须等待当前这个执行完以后才能执行,所谓的不可打断是指不可以被同一个对象的线程打断,这里同一个对象至关重要,因为java中每一个对象都有自己的一个对象锁,当该对象的某个synchronized方法被调用后,可以理解为该方法把该对象的对象锁拿走了,此时此刻,该对象的线程无论是访问这个对象的这个方法或是其它方法,只要前边带有synchronized,都不能访问,必须等待,等待当前拿着对象锁的那个方法结束。简单来说,只要有一个synchronized方法在执行,那么该对象的其他带有synchronized的方法都不能执行,须等待,只要是同一个对象的调用,就是这样,和哪个线程没关系(也就是说无论是当前执行方法所在的线程还是其他用同一个对象new出来的线程)。不过,这个时候该对象还是可以访问那些不带有synchronized的方法的。所以对于共享变量所涉及的方法都要认真考虑。

来看一个例子程序

class Cat implements Runnable{
   String voice="HH";
  public Cat(){}
  public Cat(String s){
     this.voice=s;
                      }
  public synchronized void run(){
    System.out.println(voice);
    
   try{  
    Thread.sleep(4000);}catch(Exception e){
     e.printStackTrace();}
    
   System.out.println("still"+voice);
   voice="changed";
  }
}
 public class Test{
  public static void main(String args[]){
   Cat c1=new Cat("haha");
   Cat c2=new Cat("hehe");
   Thread t1=new Thread(c1);
   Thread t2=new Thread(c1);
   t1.start();
   t2.start();



  }
}

程序中t1  ,t2是用同一个对象创建的不同线程,他们访问带有synchronized方法run,如果他们之间是没有互斥等待的,那么结果应该为

haha

hehe

stillhaha

stillchanged

但是实际结果为

haha

stillhaha

changed

stillchanged

这说明第一个线程t1改变voice时影响了t2

 

  再来说说不是同一个对象new出来的线程吧。他们之间访问同一个synchronized方法时没有任何限制,因为虽然是一个类的方法,但是来自不同的对象,大家各自访问各自的。再来看一个程序

 

class Cat implements Runnable{
   static String voice="HH";
  public Cat(){}
  public Cat(String s){
     this.voice=s;
                      }
  public synchronized void run(){
    System.out.println(voice);
    
   try{  
    Thread.sleep(4000);}catch(Exception e){
     e.printStackTrace();}
    voice="changed";
   System.out.println("still"+voice);
  }
}
 public class Test{
  public static void main(String args[]){
   Cat c1=new Cat();
   Cat c2=new Cat();
   Thread t1=new Thread(c1);
   Thread t2=new Thread(c2);
   t1.start();
   t2.start();



  }
}


t1和t2是由同一个类的不同对象创建出来的不同线程,他们共同调用run方法,其中有一个类变量voice,如果t1,t2是互斥调用的,那么结果应该为

HH

Stillchanged

changed

Stillchanged

但是实际的结果为

HH

HH

Stillchanged

Stillchanged

这说明第一个线程改变类变量voice时并没有影响到第二个线程,所以他们是不是互斥访问的。

 

 

总结:

1.对于同一个对象的任意(比如第一个程序中的t1和t2,都是由c1这同一个对象创建的)线程,访问带有synchronized方法时是互斥的,根本原因在于一个对象只有一个对象锁,这个锁在某个时间段只能由一个方法获得,当它执行完以后,才释放这把锁给其他的用。但是访问那些不带synchronized的方法则不受影响,所以对于共享变量之类的临界资源,要考虑清楚。

2.对于不同对象的线程,访问同一个synchronized方法,不受影响,因为此时有多于一把的对象锁。这个时候就要注意一下同一个类的不同对象对类变量的操作了,考虑好是不是对类变量要加锁

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值