我试图理解什么使得锁在并发如此重要,如果一个人可以使用同步(这)。在下面的虚拟代码中,我可以这样做:

同步整个方法或同步脆弱区域(Synchronized (this){…}) 或者使用ReentrantLock锁定易受攻击的代码区域。

代码:

    private final ReentrantLock lock = new ReentrantLock(); 
    private static List<Integer> ints;

    public Integer getResult(String name) { 
        .
        .
        .
        lock.lock();
        try {
            if (ints.size()==3) {
                ints=null;
                return -9;
            }   

            for (int x=0; x<ints.size(); x++) {
                System.out.println("["+name+"] "+x+"/"+ints.size()+". values >>>>"+ints.get(x));
            }

        } finally {
            lock.unlock();
        } 
        return random;
}

当前回答

从oracle文档页关于ReentrantLock:

一个可重入互斥锁,其基本行为和语义与使用同步方法和语句访问的隐式监视锁相同,但具有扩展功能。

A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. A thread invoking lock will return, successfully acquiring the lock, when the lock is not owned by another thread. The method will return immediately if the current thread already owns the lock. The constructor for this class accepts an optional fairness parameter. When set true, under contention, locks favor granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order.

ReentrantLock键的特性如本文所述

能够可中断地锁定。 能力超时,而等待锁定。 创造公平锁的权力。 API来获取等待锁的线程列表。 灵活地尝试锁定而不阻塞。

你可以使用ReentrantReadWriteLock。ReadLock ReentrantReadWriteLock。WriteLock以进一步获得对读写操作的粒度锁的控制。

看看Benjamen关于不同类型ReentrantLocks使用的文章吧

其他回答

有一件事要记住: 名称“ReentrantLock”给出了关于其他锁定机制的错误信息,即它们不是可重入的。这是不对的。通过“synchronized”获得的锁在Java中也是可重入的。

关键的区别是“同步”使用内在锁(每个对象都有),而锁API没有。

让我们假设这段代码运行在一个线程中:

private static ReentrantLock lock = new ReentrantLock();

void accessResource() {
    lock.lock();
    if( checkSomeCondition() ) {
        accessResource();
    }
    lock.unlock();
}

由于线程拥有锁,它将允许多次调用lock(),因此它将重新进入锁。这可以通过引用计数来实现,这样它就不必再次获得锁。

同步锁不提供任何等待队列机制,在其中一个线程执行后,任何并行运行的线程都可以获得锁。因此,在系统中运行较长时间的线程永远没有机会访问共享资源,从而导致饥饿。

重入锁非常灵活,并且有一个公平策略,如果一个线程等待较长时间,在当前执行的线程完成后,我们可以确保等待较长的线程获得访问共享资源的机会,从而降低系统的吞吐量,使其更加耗时。

您可以使用带有公平策略或超时的重入锁来避免线程饥饿。您可以应用线程公平策略。这将有助于避免线程永远等待获取资源。

private final ReentrantLock lock = new ReentrantLock(true);
//the param true turns on the fairness policy. 

“公平策略”选择下一个要执行的可运行线程。它是基于优先级,从上次运行到现在的时间等等

同时, 同步如果不能脱离阻塞,可以无限阻塞。Reentrantlock可以设置超时。

从oracle文档页关于ReentrantLock:

一个可重入互斥锁,其基本行为和语义与使用同步方法和语句访问的隐式监视锁相同,但具有扩展功能。

A ReentrantLock is owned by the thread last successfully locking, but not yet unlocking it. A thread invoking lock will return, successfully acquiring the lock, when the lock is not owned by another thread. The method will return immediately if the current thread already owns the lock. The constructor for this class accepts an optional fairness parameter. When set true, under contention, locks favor granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order.

ReentrantLock键的特性如本文所述

能够可中断地锁定。 能力超时,而等待锁定。 创造公平锁的权力。 API来获取等待锁的线程列表。 灵活地尝试锁定而不阻塞。

你可以使用ReentrantReadWriteLock。ReadLock ReentrantReadWriteLock。WriteLock以进一步获得对读写操作的粒度锁的控制。

看看Benjamen关于不同类型ReentrantLocks使用的文章吧