Two mutex mechanisms:
1,synchronized
2,ReentrantLock
ReentrantLock is a new feature of jdk5. ReentrantLock can completely replace the traditional synchronized locking mechanism. It is more object-oriented and flexible to adopt ReentrantLock. There are many articles on comparing the two locking modes on the internet. There are not many words here. baidu and google just drop out. In this blog, we also write a classic example of the implementation of these two kinds of locks, Producer and Consumer.
synchronized mode: "java Threads: Three Ways to Realize Producer-Consumer Problem _1"
ReentranLock mode: "java Threads: Three Ways to Realize Producer-Consumer Problem _2"
As for read-write locks, language interpretation is better than code interpretation. Here are two examples to illustrate the use of read-write locks and read-write locks:
Example 1:
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.locks.ReadWriteLock;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- /**
- * @author amber2012
- *
- * ReadWriteLock
- *
- * In multi-threaded environment, reading and writing the same data will involve thread security. For example, when one thread reads data, another thread reads data in the
- * Writing data results in inconsistency between the front and back data; when one thread writes data, the other thread writes, which also results in the data that the thread sees before and after.
- * Inconsistency.
- *
- * At this time, mutex can be added to the read-write method. At any time, only one read or write operation of one thread can be allowed, and no read or write operation of other threads can be allowed.
- * Such a problem can be solved, but the efficiency is greatly discounted. Because in a real business scenario, the number of operations to read data is usually high.
- * In the operation of writing data, the read-read operation between threads does not involve thread safety. There is no need to add mutex, as long as it is in the read-write, write-write period.
- * Just lock it in between.
- *
- * For this situation, read-write lock is the best solution!
- *
- * The mechanism of read-write locks:
- * "Read-Read "No Mutual Exclusion"
- * "Read-Write Mutual Exclusion
- * "Write-Write Mutual Exclusion
- *
- * That is to say, at all times it must be guaranteed that:
- * Only one thread is writing;
- * When the thread is reading, the write operation waits.
- * When a thread is writing, the write and read operations of other threads have to wait.
- *
- * Here is a cache class for demonstrating the operation of read-write locks: reentry, degradation
- */
- public class CachedData {
- //Caches should be singletons, which are designed in singleton mode.
- private static CachedData cachedData = new CachedData();
- private final ReadWriteLock lock = new ReentrantReadWriteLock();//Read write lock
- private Map<String, Object> cache = new HashMap<String, Object>();//cache
- private CachedData(){
- }
- public static CachedData getInstance(){
- return cachedData;
- }
- //Read cache:
- public Object read(String key) {
- lock.readLock().lock();
- Object obj = null;
- try {
- obj = cache.get(key);
- if (obj == null) {
- lock.readLock().unlock();
- //In this case, other threads may acquire locks
- lock.writeLock().lock();
- try {
- if (obj == null) {
- obj = "Find the database"; //The actual action is to find the database
- //Update the data to the cache:
- cache.put(key, obj);
- }
- } finally {
- //In the process of acquiring the write lock, the current thread can acquire the read lock, which is called the lock reentry, and then leads to the degradation of the write lock, called the degraded lock.
- //Write locks can be degraded by reentrant, but only when all write locks held by the current thread have been released can reentrant reader be allowed to use
- //They are. So in the reentrant process, other threads will not have access to locks (the benefits of doing so). Imagine releasing the write lock first.
- //What are the disadvantages of reading locks? If you do, you may be interrupted by other threads after releasing the write lock and before getting the read lock.
- //Step of reentry - > degraded lock: first get the write lock, then get the read lock, and finally release the write lock (emphasis)
- lock.readLock().lock();
- lock.writeLock().unlock();
- }
- }
- } finally {
- lock.readLock().unlock();
- }
- return obj;
- }
- }
Example 2:
- import java.util.Map;
- import java.util.TreeMap;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReadWriteLock;
- import java.util.concurrent.locks.ReentrantReadWriteLock;
- import javax.xml.crypto.Data;
- /**
- * @author amber2012
- *
- * jdk A good example of the use of the ReentrantReadWriteLock class in the document is given below.
- *
- * ReentrantReadWriteLock can be used to improve concurrency when using some kinds of Collections. Usually, in anticipation of collection
- * Very large, reader threads access it more than writer threads, and entail operations cost more than synchronization overhead, which is worth trying. For example, the following
- * TreeMap is a class that uses TreeMap and is expected to be large and accessible at the same time.
- */
- public class RWDictionary {
- private final Map<String, Data> map = new TreeMap<String, Data>();
- private final ReadWriteLock rwl = new ReentrantReadWriteLock();
- private final Lock readLock = rwl.readLock();
- private final Lock writeLock = rwl.writeLock();
- public Data get(String key) {
- readLock.lock();
- try {
- return map.get(key);
- } finally {
- readLock.unlock();
- }
- }
- public String[] allKeys() {
- readLock.lock();
- try {
- return (String[]) map.keySet().toArray();
- } finally {
- readLock.unlock();
- }
- }
- public Data put(String key, Data value) {
- writeLock.lock();
- try {
- return map.put(key, value);
- } finally {
- writeLock.unlock();
- }
- }
- public void clear() {
- writeLock.lock();
- try {
- map.clear();
- } finally {
- writeLock.unlock();
- }
- }
- }