Lock and synchronization in Java
Java objects:
length | content | Explain |
---|---|---|
32/64bit | Mark Word | Store the hashCode or lock information of the object |
32/64bit | Class Metadata Address | Pointer to object type data |
32/64bit | Array length | The length of the array (if the current object is an array) |
MarkWorld content
Locks in Java
Fair lock and unfair lock
- Both fair and unfair lock queues are based on a two-way linked list maintained within the lock. The value of Node in the table is the thread requesting the current lock. The fair lock is to take values from the team leader in turn, first in, first out.
- The implementation of lock is based on the following points:
- volatile keywords for table Node and state state.
- Atomic operation of compareAndSet
Reetranlock is a fair lock only when it is passed in true.
public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); }
Default fair lock
/** * Creates an instance of {@code ReentrantLock}. * This is equivalent to using {@code ReentrantLock(false)}. */ public ReentrantLock() { sync = new NonfairSync(); }
First look at the unfair lock:
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
Look at the fair lock again
static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { acquire(1); } /** * Fair version of tryAcquire. Don't grant access unless * recursive call or no waiters or is first. */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }
Read write lock
public class TestReadWriteLock { private static ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private static Lock readLock = readWriteLock.readLock(); private static Lock writeLock = readWriteLock.writeLock(); /** * @param args */ public static void main(String[] args) { Thread thread1 = new Thread() { public void run() { read(); write(); }; }; Thread thread2 = new Thread() { public void run() { read(); write(); }; }; thread1.start(); thread2.start(); } //Read operation public static void read(){ readLock.lock(); try{ System.out.println(Thread.currentThread().getName()+" read something..."); }catch(Exception e){ System.out.println(Thread.currentThread().getName()+" catch exception..."); }finally{ readLock.unlock(); } } //Write operation public static void write(){ writeLock.lock(); try{ System.out.println(Thread.currentThread().getName()+" write something..."); }catch(Exception e){ System.out.println(Thread.currentThread().getName()+" catch exception..."); }finally{ writeLock.unlock(); } } }
Reentrant lock synchronized is reentrant lock
public class TestReetrnSynchronized { public static void main(String[] args) { /** * Both methods method1 and method2 are modified with synchronized. If thread A executes to method1 at A certain time, * At this time, thread A obtains the lock of this object, and since method 2 is also synchronized, if synchronized does not have reentrancy, * At this time, thread A needs to reapply the lock. But that creates A problem. * Because thread A already holds the lock of the object, and is applying to acquire the lock of the object, thread A will wait for the lock that will never be acquired. */ testMethod1(); } /** * */ private synchronized static void testMethod1() { System.out.println(" Entry method testMthodd1"); testMethod2(); } /** * */ private synchronized static void testMethod2() { System.out.println(" Entry method testMthodd2"); } }
Pessimistic lock