多线程对不同对象的锁定

时间:2016-03-21 08:00:26

标签: java multithreading

我是java编程的新手,我知道多线程在Java中不是一个简单的主题,我也是C开发人员近3年。

我读过这个主题:“Multiple locks - Behind the scene”我完全理解,但我有一个问题。

我更新代码如下:

package multithreading;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Worker {

    private List<Integer> list1 = new ArrayList<Integer>();
    private List<Integer> list2 = new ArrayList<Integer>();

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    private void updateList1(int i) {
        synchronized (lock1) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex);
            }
            list1.add(1);
        }
    }

    private void updateList2(int i) {
        synchronized (lock2) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex);
            }
            list2.add(1);
        }
    }

    public void process(int ii) {
        for (int i = 0; i < 1000; i++) {
            updateList1(ii);
            updateList2(ii);
        }
    }

    public void execute() {
        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                process(1);
            }
        });

        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                process(2);
            }
        });

        long start = System.currentTimeMillis();

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(Worker.class.getName()).log(Level.SEVERE, null, ex);
        }

        long end = System.currentTimeMillis();

        System.out.println("Time taken: " + (end - start));
        System.out.println("List1: " + list1.size() + "; list2: " + list2.size());
    }
}

在主类中我创建了一个对象并调用了execute方法,输出为:

Time taken: 2186 List1: 2000; list2: 2000

但是,如果我使两个函数(updateList1,updateList2)都为synchronized并删除lock1lock2上的同步块

主要输出:

Time taken: 4342 List1: 2000; list2: 2000

关注的是execute()调用updateList1()内的代码,然后是updateList2(),因此它是对第一个代码(使用synchronized块)中的两个方法的顺序调用一个线程获取lock1而另一个线程试图调用updateList1()它将等待另一个线程释放lock1。因此,两种实施方式的时间必须相同。

请理解答案,如果我在Java中有任何错误理解,请对不起,因为这个场景是我从C的经验中得知的。

3 个答案:

答案 0 :(得分:2)

使用synchronized方法,在任何给定时间只能执行两种方法中的一种。这导致顺序执行如下(当然还有许多其他可能性):

t1: updateList1             updateList2
t2:             updateList1             updateList2

在不同的锁定对象上使用synchronized语句,允许两种方法同时运行。

t1: updateList1 updateList2 updateList1 updateList2 
t2:             updateList1 updateList2 updateList1

初始步骤updateList1updateList2可以并行运行。由于这些方法需要相同的时间,因此在第二种情况下也可以获得理想的加速比率。

答案 1 :(得分:1)

时间不一样,因为在你使updateList1updateList2同步的情况下,他们使用Worker对象作为锁定实例。

所以在第二种情况下,如果一个线程正在运行updateList2,则另一个线程无法进入updateList1

答案 2 :(得分:1)

  • 对于您的第一种情况,因为锁定的对象没有应用锁定 是有区别的。
  • 对于第二种情况,删除锁定对象, 然后,锁对象现在来到Test的实例,其中 包含list1和list2。在这种情况下,当Test同步时 由Thread1访问,Thread2需要等待和反复。