Quantcast
Channel: IT社区推荐资讯 - ITIndex.net
Viewing all articles
Browse latest Browse all 11804

java 并发编程 synchronized

$
0
0
同步原语--synchronized

synchronized(class)很特别,它会让另一个线程在任何需要获取class做为monitor的地方等待.class与this做为不同的监视器可以同时使用,不存在一个线程获取了class,另一个线程就不能获取该class的一切实例.


[list]
  • ->线程各自获取monitor,不会有等待.
  • synchronized(class)
    synchronized(this)

  • ->如果不同线程监视同一个实例对象,就会等待,如果不同的实例,不会等待.
  • synchronized(this)
    synchronized(this)

  • ->如果不同线程监视同一个实例或者不同的实例对象,都会等待.
  • synchronized(class)
    synchronized(class)

    [/list]

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

    接着来讨论synchronized用到不同地方对代码产生的影响:

    假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。

    1. 把synchronized当作函数修饰符时,示例代码如下:

    Public synchronized void methodAAA()
    
    {
    
    //….
    
    }


    这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了

    synchronized关键字的方法。

    上边的示例代码等同于如下代码:

    public void methodAAA()
    
    {
    
    synchronized (this)      // (1)
    
    {
    
           //…..
    
    }
    
    }


    (1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱:(

    2.同步块,示例代码如下:

    public void method3(SomeObject so)
    
    {
    
        synchronized(so)
    
        { 
           //….. 
        }
    
    }


    这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

    class Foo implements Runnable
    
    {
    
            private byte[] lock = new byte[0]; // 特殊的instance变量
    
            Public void methodA() 
            {
    
               synchronized(lock) { //… }
    
            }
    
            //…..
    
    }


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

    3.将synchronized作用于static 函数,示例代码如下:

    Class Foo 
    {
    
        public synchronized static void methodAAA()   // 同步的static 函数 
        { 
            //…. 
        }
    
        public void methodBBB() 
        {
    
           synchronized(Foo.class)   // class literal(类名称字面常量)
    
        } 
    }


       代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。

    记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。
    [/list]



    已有 0人发表留言,猛击->> 这里<<-参与讨论


    ITeye推荐




    Viewing all articles
    Browse latest Browse all 11804

    Trending Articles