Java lock mechanism (synchronized and Lock)

In java, solve the synchronization problem, very often use the synchronized and Lock, lock mechanism both of which are commonly used in multi-threaded time.

synchronized in java is a keyword that is a feature built-in java. When a thread after being synchronized access to a modified block of code will automatically get a corresponding lock and execute the code block other threads want to access this block of code, would have been in a wait state, the thread releases the lock so on its own other thread resource competition, the competition to get the thread to lock access to the code block.

  There are two thread releases the synchronized block of code lock modified way:

  1. After the thread executes a corresponding code block, the lock is automatically released.
  2. In executing the code block is an abnormality has occurred, JVM will automatically release the lock.

  To achieve synchronization using the synchronized keyword, it will lead to if there are multiple threads want to execute the code block, and the current thread has acquired the lock does not release the lock, can be imagined, only one other threads to wait, it will seriously impression execution effectiveness. Lock appears lock mechanism is to solve this phenomenon. Lock is a java interface that can be synchronized by this interface, use Lock, users must manually lock release, or prone to deadlock.        

  ReentranLock is the only class that implements the Lock. The following outlines the difference ReentranLock and synchronized:

  • Synchronized is a synchronization lock. When a thread A modified block access synchronized, thread A will acquire the lock code block, then if there are other thread scope of this block will block, but does not affect other threads to access non-synchronized block .
  • ReentranLock is reentrant lock. From the construction method, the lock mode supports two locks, lock fair and unfair lock. The default is non-fair.

  Fair lock: When the thread A to gain access to the object, the lock is acquired, then there is an internal counter num + 1, another thread wants to access the object, it will be queued (most waiting queue before a thread is to be awake), a until the thread releases the lock (num = 0), this case will wake up the thread to be awake state in the operation to acquire the lock, has been circulating. If thread A attempts to acquire the object lock that checks the object lock release is already occupied, if occupied, will make a judgment whether the current thread holding the lock, if it is an internal counter num + 1, and do not need to wait to enter again queue, but directly back to the current locks.

  Unfair Lock: When thread A after releasing the lock, the thread waiting for that object will be competition for resources, the success of the competition thread will acquire the lock, other threads continue to sleep.

  Fair lock is strictly a FIFO manner lock the competition, but unfair competition lock lock is disordered, just release the lock thread to a large extent can more quickly get to the lock queue thread can wait, so unfair lock may be a problem "hunger" of. But repeated lock acquisition can reduce the switching between threads, and equitable lock switch is a critical thread, so the impact on the operating system is relatively large, it is unfair lock throughput is greater than the fair locks, which is Why would unfairly lock JDK as the default implementation.

  Here is a Method in interface Lock:

  

  Attach Interface Lock test methods, you have any questions welcome you to leave comments.

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
    // ReentrantLock为Lock的唯一实现类
    private Lock lock = new ReentrantLock();

    /**
     * 测试使用lock 的 lock()方法 :如果锁已经被其他线程获取,则等待
     * @param thread
     */
    public void testLock(Thread thread){
        try {
            // 1.获取锁
            lock.lock();
            System.out.println("线程 " + thread.getName() + " 获取了锁!");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("线程 " + thread.getName() + " 释放了锁!");
            // 必须在 finally 中释放锁,防止死锁
            lock.unlock();
        }
    }

    /**
     * 测试使用lock 的 lock()方法 :通过这个方法去获取锁时,如果线程正在等待获取锁,则这个线程能够响应中断,即中断线程的等待状态。
     * @param thread
     */
    public void testLockInterruptibly(Thread thread){
        try {
            // 1.获取锁
            lock.lockInterruptibly();
            System.out.println("线程 " + thread.getName() + " 获取了锁!");
            Thread.sleep(3000);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            System.out.println("线程 " + thread.getName() + " 释放了锁!");
            // 必须在 finally 中释放锁,防止死锁
            lock.unlock();
        }
    }

    /**
     * 测试使用lock 的 tryLock()方法 :如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false
     * @param thread
     */
    public void testTryLock(Thread thread){
        if(lock.tryLock()){// 如果获取到了锁
            try {
                System.out.println("线程 " + thread.getName() + " 获取了锁!");
                Thread.sleep(3000);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                System.out.println("线程 " + thread.getName() + " 释放了锁!");
                // 必须在 finally 中释放锁,防止死锁
                lock.unlock();
            }
        }else {
            // 没有获取到锁
            System.out.println("线程 " + thread.getName() + " 没有获取到锁!");
        }
    }

    /**
     * 测试使用lock 的 tryLock(long time, TimeUnit unit)方法 :和tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待一定的时间,
     * 在时间期限之内如果还拿不到锁,就返回false。如果如果一开始拿到锁或者在等待期间内拿到了锁,则返回true。
     * @param thread
     */
    public void testTryLock_time_unit(Thread thread){
        try {
            if(lock.tryLock(1000, TimeUnit.MILLISECONDS)){// 如果获取到了锁
                try {
                    System.out.println("线程 " + thread.getName() + " 获取了锁!");
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    System.out.println("线程 " + thread.getName() + " 释放了锁!");
                    // 必须在 finally 中释放锁,防止死锁
                    lock.unlock();
                }
            }else {
                // 没有获取到锁
                System.out.println("线程 " + thread.getName() + " 没有获取到锁!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args){
        TestLock testLock = new TestLock();
        Thread a = new Thread("A") {
            @Override
            public void run() {
                /*// 测试 lock()
                testLock.testLock(Thread.currentThread());*/
                /*// 测试 lockInterruptibly()
                testLock.testLockInterruptibly(Thread.currentThread());*/
                /*// 测试 tryLock()
                testLock.testTryLock(Thread.currentThread());*/
                /*// 测试 tryLock(long time, TimeUnit unit)
                testLock.testTryLock_time_unit(Thread.currentThread());*/
                testLock.testTryLock_time_unit(Thread.currentThread());
            }
        };
        Thread b = new Thread("B") {
            @Override
            public void run() {
                testLock.testTryLock(Thread.currentThread());
            }
        };
        a.start();
        b.start();
    }
}
复制代码

Reproduced in: https: //juejin.im/post/5cf530fdf265da1bc854140e

Guess you like

Origin blog.csdn.net/weixin_33743248/article/details/91454948