java同步技术的几种方法探讨

1. 对象实例的锁
  1. class Test{   
  2. //第一种同步方式   
  3. public synchronized void f1(){   
  4.   
  5. //do something here    
  6.   
  7.    }   
  8.   
  9. //第二种同步方式   
  10. public void f2(){   
  11.   
  12. synchronized(this){   
  13.   
  14. //do something here    
  15.   
  16.     }   
  17.   
  18.    }   
  19.   
  20. }   
class Test{ 
//第一种同步方式
public synchronized void f1(){ 

//do something here 

   } 

//第二种同步方式
public void f2(){ 

synchronized(this){ 

//do something here 

    } 

   } 

} 

上面的f1()和f2()效果一致, synchronized取得的锁都是Test某个实列(this)的锁. 比如: Test t = new Test();

线程A调用t.f2()时, 线程B无法进入t.f1(),直到t.f2()结束。解说:这也就是同步方法,那这时synchronized锁定的是哪个对象呢?他锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,他们(同一个实例里的同步方法们)之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却能够任意调用这个被加了synchronized关键字的方法。

    那个拿到了P1对象锁的线程,才能够调用P1的同步方法,而对P2而言,P1这个锁和他毫不相干,程式也可能在这种情形下摆脱同步机制的控制,造成数据混乱。

作用: 同一个实例的同步方法在多线程中访问时会有同步效果.

 

2. class的锁

class Test{

    final static byte[] o= new byte[0];  //可以为静态,也可以非静态,看你的需求咯

   //同步方式3

    public static synchronized void f1(){

       //do something here

           }

    //同步方式4

    public static void f2(){

    synchronized(Test.class){

    //do something here

        }

     }

   //同步方式5

    public static void f3(){

        try {

              synchronized (Class.forName("Test")){

              //do something here

            }

      } catch (ClassNotFoundException ex) {

       }

     }

 

   //同步方式6

    public static void g(){

        synchronized(o){

       //do something here

              }

     }

}

解说:

上面f1(),f2(),f3(),g()效果一致

f1(),f2(),f3()中synchronized取得的锁都是Test.class的锁.

g()是自己产生一个对象o,利用o的锁做同步

作用: 多线程中访问此类或此类任一个实例的同步方法时都会同步.(同一个类中多个同步方法是否回受影响呢?比如P1访问了同步方法a1(), 那么P2还能访问同步方法a2()吗?)

注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Objectlock = new Object()则需要7行操作码。

大笑

 

3.静态方法同步

 

  1. class Test{   
  2.   
  3.     private static int v = 0;   
  4.   
  5.   
  6.     public static void f1(){   
  7.   
  8.     //do something, 但函数中没用用到v    
  9.   
  10.    }   
  11.   
  12.   
  13.    public synchronized static void f2(){   
  14.   
  15.        //do something, 函数中对v进行了读/写.    
  16.   
  17.     }   
  18.   
  19. }   
class Test{ 

    private static int v = 0; 


    public static void f1(){ 

    //do something, 但函数中没用用到v 

   } 


   public synchronized static void f2(){ 

       //do something, 函数中对v进行了读/写. 

    } 

} 

多线程中使用Test的某个实列时,

(1) f1()是线程安全的,不需要同步

(2) f2()这个静态方法中使用了函数外静态变量,所以需要同步.

 

更有一些技巧能够让我们对共享资源的同步访问更加安全:
1.  定义private 的instance变量+他的 get方法,而不要定义public/protected的instance变量。假如将变量定义为public,对象在外界能够绕过同步方法的控制而直接取得他,并改变他。这也是JavaBean的标准实现方式之一。
2.  假如instance变量是个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。 这个时候就需要将get方法也加上synchronized同步,并且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值