简体   繁体   English

同步:多个锁-创建锁对象?

[英]Synchronization: multiple locks - create lock objects?

A quick (I think) concurrency question: I'm going through a multithreading course at Udemy.com, and the teacher talked through the code below. 一个快速的(我认为)并发问题:我正在Udemy.com上完成多线程课程,而老师讲了下面的代码。 Although he explained it, I'm still not sure why you would create the lock1 and lock2 objects rather than locking on list1 and list2 . 尽管他解释了这一点,但我仍然不确定为什么要创建lock1lock2对象而不是锁定list1list2

App.java: App.java:

public class App {

    public static void main(String[] args) {
        Worker worker = new Worker();
        worker.main();
    }
}

Worker.java: Worker.java:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class Worker {

    private Random random = new Random();

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

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

    public void stageOne() {

        synchronized (lock1) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            list1.add(random.nextInt(100));
        }

    }

    public void stageTwo() {

        synchronized (lock2) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            list2.add(random.nextInt(100));
        }

    }

    public void process() {
        for(int i=0; i<1000; i++) {
            stageOne();
            stageTwo();
        }
    }

    public void main() {
        System.out.println("Starting ...");

        long start = System.currentTimeMillis();

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                process();
            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                process();
            }
        });

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

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();

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

I don't think the motivation for that is expressed in the code you gave, but it is generally a best practice. 我不认为对的动机在你给的代码表示,但它通常最好的做法。 However, the same best practice demands that the lock objects be final as well. 但是,相同的最佳实践也要求锁定对象也是final

If the lists in question were either accepted from the outside or exposed to the outside via a method, then the benefit of the separate lock objects becomes more obvious: it is never a good idea to expose your locks to alien code because the alien code can then use them on its own for locking, breaking your own usage pattern. 如果有问题的列表是从外部接受的,或者是通过某种方法暴露给外部的,那么单独的锁对象的好处就变得更加明显:将您的锁暴露给外来代码永远不是一个好主意,因为外来代码可以然后单独使用它们进行锁定,从而破坏您自己的使用模式。

If the lists are strictly private, then their monitors would be usable for internal locking; 如果列表严格保密,那么它们的监视器将可用于内部锁定; however, a later change to the access policy on the lists may inadvertently affect the locking policies. 但是,以后对列表上的访问策略进行更改可能会无意中影响锁定策略。 So, starting out with private locks also serves to avoid any future bugs. 因此,从私人锁开始也可以避免将来出现任何错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM