主题:深入理解同步

时间:2013-12-18 21:25:17

标签: multithreading concurrency locking synchronized

我只是想在同步时更深入地了解内在机制。我准备了3个例子。我有问题涉及他们每个人。所以这是第一个例子:


public class SyncExamples 
{

    SyncClass sync1, sync2;


    public void execute1()
    {
        sync1 = new SyncClass();
        sync1.process();
    }


    public void execute2()
    {
        sync2 = new SyncClass();
        sync2.process();
    }



    class SyncClass
    {

        public synchronized void process()
        {

        }
    }
}

SyncClass的方法process()是同步的。但是由于在SyncExamples类中创建了两个不同的对象的SyncClass,它们都可以同时执行,而不是它们。它们引用不同的对象,因此没有任何同步。是不是?

第二个例子:


public class SyncExamples 
{

    SyncClass sync1 = new SyncClass();


    public void execute1()
    {       
        sync1.process();
    }


    public void execute2()
    {       
        sync1.process();
    }




    class SyncClass
    {

        public synchronized void process()
        {

        }
    }
}

所以在这个例子中他们引用了同一个对象。所以这里有一个互斥锁。他们是同步的。但让我们来看看对我来说最有趣的例子。


public class SyncExamples 
{

    SyncClass sync1 = new SyncClass();
    ReadWriteLock lock = new ReentrantReadWriteLock(); 


    public void execute1()
    {       
        lock.writeLock().lock();
        sync1.process();
        lock.writeLock().unlock();
    }


    public void execute2()
    {       
        execute1();
    }


    public void execute3()
    {       
        sync1.process();
    }


    public void execute4()
    {       
        execute1();
    }


    class SyncClass
    {

        public void process()
        {

        }
    }
}

execute2()启动execute1()。 execute1()锁定sync1.process()。因此,execute4()必须等到execute1()解锁sync1.process()。但是execute3()怎么样?它没有引用execute1(),而是直接调用sync1.process()而没有任何锁定。所以execute1()设置的锁对execute3()无效?是对的吗?锁只对那些引用execute1()的调用有效,因为这个方法定义了一个锁?

我在一天后添加了以下示例:


public class SyncExamples 
{

    List list = new ArrayList(); 


    public void processList1()
    {       
        synchronized(list)
        {
        }
    }


    public void processList2()
    {       
        synchronized(list)
        {
        }
    }


    public void execute3()
    {       
        processList1();
    }


    public void execute4()
    {       
        processList2();
    }
}

我想澄清这最后一​​个例子。 现在我有一个我要同步的列表。方法processList1()同步list ...方法processList2()也是如此。但它们可以同时执行吗? 同步是否全局锁定列表(我的意思是所有来自其他方法的其他访问)或仅与特定方法结合使用?我仍然不明白在这个例子中是否可以同时执行execute3()和execute4(),因为它们引用了不同的方法。已同步可防止对其块进行第二次访问。但是有几种方法想要访问列表并且他们使用自己的同步块。因此,如果processList1()锁定列表,那么此列表是否会为processList2()锁定?或者这个锁对processList2()无效,因为它是一个不同的方法?

1 个答案:

答案 0 :(得分:0)

第一个问题:正确的 第二种情况:是的,就像互斥体一样 第三个问题:正确


回答编辑

synchronized块使用其参数对象作为块的锁(或更好的是,互斥锁)。因此,如果两个线程到达同一对象上的关键部分synchronized,则只允许一个线程进入其临界区,而另一个线程等待直到该临界区退出。

synchronized方法只是synchronized块的语法糖,所以

class SyncClass
{
    public synchronized void process()
    {

    }
}

可以写成

class SyncClass
{
    public void process()
    {
        synchronized(this)
        {
            // whole body of process() inside this block
        }
    }
}

所以,回答你的问题

  • synchronized将全局锁定list(或用作其参数的任何其他对象),而不仅仅是针对特定方法。您可以在代码中的任何位置同步对象,并且同步部分将以互斥方式运行,而不管包含的方法/类或调用层次结构等。
  • processList1()processList2()不会同时执行。一次只能执行一个。 (这假设您没有synchonized块之外的代码。)
  • execute3()和execute4()可以同时执行,但只能到达synchronized部分。也就是说,调用processList1()processList2()以及调用execute3/4()方法之前的任何代码都可以同时执行,但synchronized部分内的代码不能同时执行。< / LI>