Java Multithreading 13: Comparison of Read-Write Locks and Two Synchronization Methods

Reprinted from: http://www.cnblogs.com/xrq730/p/4855631.html


Overview of ReentrantReadWriteLock

A very important piece of content in a large website is the reading and writing of data. Although ReentrantLock has the effect of complete mutual exclusion (that is, only one thread is executing the task behind the lock at the same time), its efficiency is very low. Therefore, a read-write lock ReentrantReadWriteLock is provided in the JDK, which can speed up the operation efficiency.

Read-write locks represent two locks, one is a lock related to read operations, called a shared lock ; the other is a lock related to write operations, called an exclusive lock . I understand these two operations as three sentences:

1. Read and read are not mutually exclusive, because read operations will not have thread safety issues

2. Mutual exclusion between write and write to avoid one write operation affecting another write operation, causing thread safety issues

3. Mutual exclusion between read and write, to avoid the write operation modifying the content during the read operation, causing thread safety issues

To sum up, multiple Threads can perform read operations at the same time, but only one Thread is allowed to perform write operations at the same time .

 

read and read sharing

First prove the first sentence "read and read are not mutually exclusive", give a simple example:

copy code
public class ThreadDomain48 extends ReentrantReadWriteLock
{        
    public void read()
    {
        try
        {
            readLock().lock();
            System.out.println(Thread.currentThread().getName() + "Acquired read lock, time is" + 
                    System.currentTimeMillis());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace ();
        }
        finally
        {
            readLock().unlock();
        }
    }
}
copy code
copy code
public static void main(String[] args)
{
    final ThreadDomain48 td = new ThreadDomain48();
    Runnable readRunnable = new Runnable()
    {
        public void run()
        {
            td.read();
        }
    };
    Thread t0 = new Thread(readRunnable);
    Thread t1 = new Thread(readRunnable);
    t0.start();
    t1.start();
}
copy code

Take a look at the running results:

Thread- 0 acquired the read lock for 1444019668424
Thread - 1 acquired the read lock for 1444019668424

Although the method is locked and sleeps for 10 seconds, the two threads still execute the code behind the lock() method at almost the same time, as you can tell by the time. It shows that the lock.readLock() read lock can improve the efficiency of program operation and allow multiple threads to execute the code behind the lock() method at the same time

 

write and write mutex

Prove the second sentence "write and write are mutually exclusive", a similar proof method:

copy code
public class ThreadDomain48 extends ReentrantReadWriteLock
{        
    public void write()
    {
        try
        {
            writeLock().lock();
            System.out.println(Thread.currentThread().getName() + "Obtained write lock, time is" + 
                    System.currentTimeMillis());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace ();
        }
        finally
        {
            writeLock().unlock();
        }
    }
}
copy code
copy code
public static void main(String[] args)
{
    final ThreadDomain48 td = new ThreadDomain48();
    Runnable readRunnable = new Runnable()
    {
        public void run()
        {
            td.write();
        }
    };
    Thread t0 = new Thread(readRunnable);
    Thread t1 = new Thread(readRunnable);
    t0.start();
    t1.start();
}
copy code

Take a look at the running results:

Thread- 0 acquired the write lock for 1444021393325
Thread - 1 acquired the write lock for 1444021403325

It can be seen from the time that 10000ms is 10s, which is consistent with the code, which proves that reading and reading are mutually exclusive.

 

read and write mutually exclusive

Finally, prove that the third sentence "reading and writing are mutually exclusive". The proof method is nothing more than combining the above two. Let's take a look:

copy code
public class ThreadDomain48 extends ReentrantReadWriteLock
{        
    public void write()
    {
        try
        {
            writeLock().lock();
            System.out.println(Thread.currentThread().getName() + "Obtained write lock, time is" + 
                    System.currentTimeMillis());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace ();
        }
        finally
        {
            writeLock().unlock();
        }
    }
    
    public void read()
    {
        try
        {
            readLock().lock();
            System.out.println(Thread.currentThread().getName() + "Acquired read lock, time is" + 
                    System.currentTimeMillis());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace ();
        }
        finally
        {
            readLock().unlock();
        }
    }
}
copy code
copy code
public static void main(String[] args)
    {
        final ThreadDomain48 td = new ThreadDomain48();
        Runnable readRunnable = new Runnable()
        {
            public void run()
            {
                td.read();
            }
        };
        Runnable writeRunnable = new Runnable()
        {
            public void run()
            {
                td.write();
            }
        };
        Thread t0 = new Thread(readRunnable);
        Thread t1 = new Thread(writeRunnable);
        t0.start();
        t1.start();
    }
copy code

Take a look at the running results:

Thread- 0 acquired the read lock for 1444021679203
Thread - 1 acquired the write lock for 1444021689204

From the time point of view, it is also 10000ms or 10s, which is consistent with the code, which proves that reading and writing are mutually exclusive. Note that "read and write mutual exclusion" and "write and read mutual exclusion" are two different scenarios, but the proof method and conclusion are the same, so we won't prove it.

 

Comparison of synchronized and ReentrantLock

So far, in multi-threading, there are two ways to lock: synchronized and ReentrantLock. The two locking methods have their own advantages and disadvantages. The following is a brief comparison:

1. Synchronized is a keyword, just like if...else..., it is an implementation at the syntax level, so synchronized acquiring locks and releasing locks are all done by the Java virtual machine to help users; ReentrantLock is a class-level implementation, so The acquisition of locks and the release of locks require users to operate by themselves. Special reminder again, ReentrantLock is finished after lock(), you must manually unlock()

2. Synchronized is simple, simple means inflexible, and the locking mechanism of ReentrantLock provides users with great flexibility. This is reflected most vividly in Hashtable and ConcurrentHashMap. A synchronized lock locks the entire Hash table, while ConcurrentHashMap uses ReentrantLock to achieve lock separation, and the lock is only the segment instead of the entire Hash table

3. Synchronized is an unfair lock, and ReentrantLock can specify whether the lock is fair or unfair

4. The threads notified by synchronized implements the waiting/notification mechanism are random, and ReentrantLock implements the waiting/notification mechanism to selectively notify

5. Compared with synchronized, ReentrantLock provides users with multiple methods for acquiring lock information, such as knowing whether the lock is acquired by the current thread, how many times the lock is called by the same thread, whether the lock is acquired by any thread, etc.

To sum up, I think if you only need to lock simple methods and simple code blocks, then consider using synchronized, and consider using ReentrantLock in complex multi-threading scenarios . Of course, this is only a suggestion, and it still needs to be analyzed in a specific scenario.

Finally, after checking a lot of information, the JDK1.5 version only has many optimizations for synchronized, and the efficiency of synchronized and ReentrantLock should be similar.


Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326899415&siteId=291194637