关于ReentrantLock的介绍网上好文章很多,写的很详细,但对于不太想深入了解,但又马上想用的人可能就有点麻烦了。本文的目的是直接演示使用方法,帮助大家快速入门。
使用ReentrantLock就是为了实现线程间的同步
示例1
private Lock lock = new ReentrantLock(); private void test(){ new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "thread 1"); lock.lock(); Log.d(TAG, "lock 1"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } lock.unlock(); Log.d(TAG, "unlock 1"); } }).start(); new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "thread 2"); lock.lock(); Log.d(TAG, "lock 2"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } lock.unlock(); Log.d(TAG, "unlock 2"); } }).start(); }
执行结果
06-10 10:06:16.618 1947-1985/com.example.test.myapplication D/MainActivity: thread 1 06-10 10:06:16.618 1947-1985/com.example.test.myapplication D/MainActivity: lock 1 06-10 10:06:16.618 1947-1986/com.example.test.myapplication D/MainActivity: thread 2 06-10 10:06:21.620 1947-1985/com.example.test.myapplication D/MainActivity: unlock 1 06-10 10:06:21.621 1947-1986/com.example.test.myapplication D/MainActivity: lock 2 06-10 10:06:26.621 1947-1986/com.example.test.myapplication D/MainActivity: unlock 2
可见,thread1调用lock.lock()获取锁之后,thread2运行到 lock.lock() 时只能等待,等thread1调用lock.unlock()之后 thread2才能获取到锁,继续执行。
也就是lock()和unlock() 之前的代码实现了线程同步,一套执行完才能进入下一个lock/unlock 对。
示例2
private Lock lock = new ReentrantLock(); private Condition c1 = lock.newCondition(); private void test(){ new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "thread 1"); lock.lock(); Log.d(TAG, "lock 1"); try { Thread.sleep(5000); Log.d(TAG, "wait 1"); c1.await(); } catch (InterruptedException e) { e.printStackTrace(); } lock.unlock(); Log.d(TAG, "unlock 1"); } }).start(); new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "thread 2"); lock.lock(); Log.d(TAG, "lock 2"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } c1.signal(); Log.d(TAG,"signal 2"); lock.unlock(); Log.d(TAG, "unlock 2"); } }).start(); }
执行结果
06-10 10:40:00.570 2051-2077/com.example.test.myapplication D/MainActivity: thread 1 06-10 10:40:00.576 2051-2077/com.example.test.myapplication D/MainActivity: lock 1 06-10 10:40:00.578 2051-2078/com.example.test.myapplication D/MainActivity: thread 2 06-10 10:40:05.586 2051-2077/com.example.test.myapplication D/MainActivity: wait 1 06-10 10:40:05.586 2051-2078/com.example.test.myapplication D/MainActivity: lock 2 06-10 10:40:10.632 2051-2078/com.example.test.myapplication D/MainActivity: signal 2 06-10 10:40:10.633 2051-2078/com.example.test.myapplication D/MainActivity: unlock 2 06-10 10:40:10.633 2051-2077/com.example.test.myapplication D/MainActivity: unlock 1
thread1获取到锁后,在线程中调用c1.await(); 开始等待,此时释放锁,thread2在lock()处获取到锁,且thread2锁内的代码执行完后,调用unlock(),thread1才会继续执行,当然,需要在thread2中使用c1.signal()通知 thread1结束等待。
那么,将thread1中的c1.await()改成 超时等待,到了时间会不会自动往下走呢?答案是不会,看例子
示例3
private Lock lock = new ReentrantLock(); private Condition c1 = lock.newCondition(); private void test(){ new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "thread 1"); lock.lock(); Log.d(TAG, "lock 1"); try { Thread.sleep(5000); Log.d(TAG, "wait 1"); c1.await(1000, TimeUnit.MILLISECONDS); Log.d(TAG, "wait timeout 1"); } catch (InterruptedException e) { e.printStackTrace(); } lock.unlock(); Log.d(TAG, "unlock 1"); } }).start(); new Thread(new Runnable() { @Override public void run() { Log.d(TAG, "thread 2"); lock.lock(); Log.d(TAG, "lock 2"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } c1.signal(); Log.d(TAG,"signal 2"); lock.unlock(); Log.d(TAG, "unlock 2"); } }).start(); }
执行结果
06-10 10:51:17.179 2142-2169/com.example.test.myapplication D/MainActivity: thread 1 06-10 10:51:17.181 2142-2169/com.example.test.myapplication D/MainActivity: lock 1 06-10 10:51:17.181 2142-2170/com.example.test.myapplication D/MainActivity: thread 2 06-10 10:51:22.189 2142-2169/com.example.test.myapplication D/MainActivity: wait 1 06-10 10:51:22.191 2142-2170/com.example.test.myapplication D/MainActivity: lock 2 06-10 10:51:27.193 2142-2170/com.example.test.myapplication D/MainActivity: signal 2 06-10 10:51:27.193 2142-2170/com.example.test.myapplication D/MainActivity: unlock 2 06-10 10:51:27.194 2142-2169/com.example.test.myapplication D/MainActivity: wait timeout 1 06-10 10:51:27.194 2142-2169/com.example.test.myapplication D/MainActivity: unlock 1
c1.await(1000, TimeUnit.MILLISECONDS); 只等待了1秒,而thread2需要运行5秒,虽然超时了,但thread2没有释放锁,thread1也只能继续等待。
总结:多个线程中lock()和unlock()间的代码必须一套跑完才能继续走下一个,当使用await释放锁后,需要等其它线程跑完整个lock()-unlock()流程才能继续。
发表评论