Ten, display lock

Before Java 5.0, when the mechanism to coordinate access to shared objects that can be used only synchronized and volatile. Java 5.0 adds a new mechanism: ReentrantLock。In contrast to the previously mentioned mechanism, ReentrantLock is not a substitute method for the built-in lock, but when the built-in locking mechanism does not apply, as an alternative of the change machine Features.

一、Lock与ReentrantLock

Defines a set of abstract interfaces Lock locking operations given Listing. The built-in locking mechanism is different, `Lock provides an unconditional, pollable, timing and a lock acquisition operation may be interrupted, all the locking and unlocking methods are explicit. In
must be provided to achieve the same internal lock Lock the visibility of memory semantics, but the semantics of the lock, the scheduling algorithm, the order assurance in performance and characteristics can vary.

public interface Lock {
    void lock();

    void lockInterruptibly() throws InterruptedException;

    boolean tryLock();

    boolean tryLock(long var1, TimeUnit var3) throws InterruptedException;

    void unlock();

    Condition newCondition();
}

ReentrantLock realized the Lock interface, and provides synchronized with the same mutex and memory visibility. When obtaining ReentrantLock, it has the same memory semantics into the synchronized block, also has a synchronized block and exit the same language more memory when released ReentrantLock. In addition, synchronized with the same, of ReentrantLock also provides reentrant locking semantics. ReentfantLock supports all defined in acquiring the lock mode Lock interface, and compared with synchronized, it provides greater flexibility to deal with the problem is not the availability of locks.
In most cases, the built-in lock can work well, but there are some limitations in function, for example, you can not interrupt a thread waiting to acquire a lock, or can not go on waiting indefinitely at the request to obtain a lock. Built-in lock must acquire the lock release block of code, which simplifies the coding, and to achieve a good interaction with the exception processing operation, but can not achieve the locking rules nonblocking structure. These are the reasons for using synchronized, but in some cases, a more flexible locking mechanisms generally provide better activity or performance.
Listing shows the use of standard forms Lock interface. This form complicated than using the built-in lock some of them: 必须在finally块中释放锁。otherwise, if an exception is thrown in the code to be protected, then this will never be able to release the lock. When using the lock you must also consider the case where an exception is thrown in the try block, if possible, so that a certain object is an inconsistent state, then a larger number of try-catch or try-fmally block. (When using some form of locking, including built-in locks, should be considered in the case of an exception.)

Lock lock = new ReentrantLock();
...
lock.lock();
try {
	// 更新对象状态
	// 捕获异常,并在必要时恢复不变性条件 
} finally {
	lock.unlock()
}

If you do not use finally to release Lock, then start up the equivalent of a time bomb. When the "bomb explosion", when, will be difficult to track the location of the first error occurs because there is no lock release position and time it should be recorded. This is the reason ReentrantLock not completely replace the synchronized: do not automatically lock when it cleared more "dangerous" because when the program execution control to leave the protected code block. While the lock is released in the finally block is not difficult, but may have forgotten.

  • 轮询锁与定时锁

The lock can be timed with a polling tryLock acquisition mode is performed by the method, compared with the unconditional lock acquisition mode, which has better error recovery mechanism built in the lock, a deadlock is a serious problem, recovery procedures the only way is to re-start the program, the only way to prevent deadlock is to avoid inconsistent lock sequence occurs when construction program. The timing of the polling can be locked to provide another option: to avoid deadlock.
If the lock can not obtain all required, you can use a polling or timing acquisition mode lock, so that f Seoul regain control, it releases the lock has been acquired, and then attempt to acquire a lock for all (or at least re- the failure of this record to the log, and other measures).
In carrying out the operation with a time limit, the time lock is also very helpful. When you call a method of a blocking operation with a time limit, it can be a time according to the remaining time. If the operation does not give results within the specified time, it will make the program a premature end. When using the built-in lock, the lock request after the start, this operation will not be canceled, so the built-in lock operation is difficult to achieve with a time limit.

  • 可中断的锁获取操作

As the timing of lock acquisition operation exclusive lock can be used with a time limit in operation, the lock acquisition operation can be interrupted likewise in the lock can be used to cancel the operation. Several mechanisms can not respond to interrupts, such as requesting the built-in lock. These non-interruptible blocking mechanisms will make the task of achieving cancel becomes complicated. locklntemiptiblyCapable of maintaining a response to interrupts while acquiring the lock, and because it is contained in Lock, so no need to create other types of deduction can not be interrupted blocking mechanism.

  • 非块结构的加锁

Built-in lock, the lock acquisition and release operations are based on a block of code - and always lock release operation to acquire the lock operation is in the same block, without considering how to exit the control block. Automatic lock release operation simplifies the analysis of the program, to avoid the possibility of coding errors, but sometimes need a more flexible locking rules.
通过降低锁的粒度可以提高代码的可伸缩性。Lock Segmentation to implement different hash hash chain based container, in order to use different locks. We can be reduced by using a similar principle lock granularity in the list, each list node shall use a separate lock, so that the different threads of different portions can independently operate the list. Each node will lock protection link pointer and the data stored in the node, so when traversing or modifying the list, we have to hold the lock on the node until the next node lock, the only way to a lock on the node before being released.

二、公平性

It offers two fairness in the selection of the constructor ReentrantLock: Create a fair and non-lock (default) or a fair lock. 在公平的锁上,线程将按照它们发出请求的顺序来获得锁,但在非公平的锁z上,则允许“插队”:当一个线程请求非公平的锁时,如果存发出请求的同时该锁的状态变为可用,那么这个线程将跳过队列中所有的等待线程并获得这个锁。(In Semaphore you can also choose to use the fair or equitable access order.) Non-equity ReentrantLock not advocate "jump the queue" behavior, but can not prevent a thread "jump the queue" at the right time. In fairness lock, if another process holds the lock money or have other threads waiting for the lock in the queue, the thread requesting a new person will be placed in the queue. In non-equitable lock only when the lock is held by a thread, a new thread request will be placed in the queue.
非公平锁的性能要高于公平锁的性能。

三、在 synchronized 和 ReentrantLock 之间进行选择

In the case of some built-in lock can not meet the demand, ReentrantLock can be used as an advanced tool. When needed should use the advanced features of ReentrantLock, these functions comprising: timing, polling can acquire the lock operation may be interrupted, fair queuing, and a lock non-block structure. Otherwise, the priority should still use synchronized.

四、读-写锁

ReentrantLock实观了一种标准的互斥锁:每次最多只有一个线程能持有ReentrantLock。But for maintaining the integrity of the data, it is usually a mutex lock too tough rules and, therefore, unnecessarily limit concurrency. Mutex lock is a conservative strategy, although avoid the "write / write" Conflict and "write / read" conflict, but also to avoid the "read / read" conflict. In many cases, the data structure of the operation is "Read" - although they are modified to be variable and in some cases, but most operations are read access operation. At this time, if the lock can be relaxed requirements, allowing multiple threads simultaneously perform a read operation to access the data structure, it will enhance the performance of the program. As long as each thread can make sure to read the latest data, and the data will not be read when there are other threads to modify the data, then it will not be a problem. In this case you can use the read / write locks:一个资源可以被多个读操作访问,或者被一个写操作访问,但两者不能同时进行。

Lock ReadWriteLock exposed the two objects, one for read and one for write operations. To read the data protection ReadWriteLock, you must first obtain a read lock, when you need to modify the data ReadWriteLock protection, you must first obtain a write lock. Although the two lock appears to be independent of each other, but read locks and write locks people just read - write lock object different views.

public interface ReadWriteLock {
    Lock readLock();

    Lock writeLock();
}

在读-写锁实现的加锁策略中,允许多个读操作同时进行.但毎次只允许一个写操作。And Lock Like, ReadWriteLock can be achieved using a variety of different ways, in terms of performance, scheduling assurance, access to priority, fairness and locking semantics, etc. may vary.

Read - write lock is a performance optimization measures, under certain circumstances to achieve higher concurrency. In practice, the data structure is often read on a multi-processor system, the read - write lock performance can be improved. In other cases, read - write lock performance than exclusive lock performance is slightly worse. This is because they have a higher complexity. To determine if in some cases the use of read - write locks whether it will bring performance gains, the best on a program for analysis. Since ReadWriteLock use Lock to achieve lock read - write portions, so if the analysis showed that the read - write lock does not improve performance, it can be easily read - write lock changed to an exclusive lock.

The interaction between the read lock and write locks may take a variety of implementations. Some alternative implementations ReadWriteLock include:

  • 释放优先。When a write operation to release people who write lock, and there is a queue threads simultaneously read and write threads, you should prefer to read a thread, the thread write, or the first to issue a request thread?
  • 读线程插队。If the lock is held by a thread to read, but write threads are waiting, the new arrival can read the thread immediately gain access to, or should we wait behind the write thread? If you read the thread before allowed to jump the queue to write a thread, it will increase concurrency, but it may cause hunger to write thread occur.
  • 重入性。Whether read lock and write lock is as heavy as the?
  • 降级。Acquires the read lock case if a thread holds the write lock, then it can not release the lock? This may make the write lock to be "downgraded" to read lock, while not allowing other threads to modify the protected resources.
  • 升级。Can read lock priority and upgraded to a write lock to read other threads and write threads are waiting for? In most read - write lock implementation does not support the upgrade, the upgrade should be displayed if no, then it is likely to cause a deadlock. (If two threads try to read at the same time upgraded to a write lock, then both read lock will not be released.)

ReentrantReadWriteLock for both locks are provided reentrant locking semantics. And ReentrantLock similar, ReentrantReadWnteLock during construction can also choose to be a fair and non-lock (default) or a fair lock. In fairness lock, the longest-waiting thread priority access to the lock. If the lock is held by the reader thread while another thread requests a write lock, then other threads can not be read to get a read lock until the thread is finished using write and release a write lock. In the non-flat lock, the thread order to gain access permission is uncertain. Write thread downgraded to read a thread is possible, but upgraded to a write writer thread thread is not possible (to do so would cause a deadlock).

And Seentranttock Similarly, write lock ReentrantReadWriteLock the only sole owner, and can only be released by a thread to acquire the lock. In Java 5.0, the read lock behavior is more akin to a lock Semaphore instead, it only maintained the number of read threads active, regardless of their identity. Modify this behavior in Java 6: Which thread has received a record audience lock.

When the lock is held for longer and most operations will not be modified guardian of resources, then read - write locks can improve concurrency. In ReadWriteMap in the ReentrantReadWriteLock to wrap Map, so that it can be safely shared between multiple threads read and still be able to avoid the "read - write" or "write - write" conflict. In reality, ConcurrentHashMap performance has been very good, so if you only need a concurrent hash-based map, then you can use this method instead of ConcurrentHashMap, but if you need to provide another Map implementations (eg LinkedHashMap) Gao access to more concurrency, you can use this technology.

public class ReadWriteMap<K,V>  {
    private final Map<K,V> map;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    private final Lock r = lock.readLock();
    private final Lock w = lock.writeLock();

    public ReadWriteMap(Map<K,V> map){
        this.map = map;
    }

    public V put(K key, V value) {
        try {
            return map.put(key, value);
        } finally {
            w.unlock();
        }
    }
    // 对remove(), putAll() , clear ()等方法执行相同的操作

    public V get(Object key) {
        r.lock ();
        try {
            return map.get(key);
        } finally {
            r.unlock();
        }
    }
    // 对其他只读的Map方法执行相同的操作

}

Guess you like

Origin blog.csdn.net/qq_27870421/article/details/90583601