实现一个显示锁
定义一个lock接口
package com.dwz.concurrency.chapter10; import java.util.Collection; public interface Lock { class TimeOutException extends Exception { public TimeOutException(String message) { super(message); } } void lock() throws InterruptedException; void lock(long mills) throws TimeOutException, InterruptedException; void unlock(); Collection<Thread> getBlockedThread(); int getBlockedSize(); }
lock的实现类
package com.dwz.concurrency.chapter10; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Optional; /** * 实现一个显示锁lock */ public class BooleanLock2 implements Lock { //The initValue is true indicated the lock have be get. //The initValue is false indicated the lock is free(other thread can get this.) private boolean initValue; private Collection<Thread> blockedThreadCollection = new ArrayList<>(); public BooleanLock2() { this.initValue = false; } @Override public synchronized void lock() throws InterruptedException { while (initValue) { blockedThreadCollection.add(Thread.currentThread()); Optional.of(Thread.currentThread().getName() + " add the blockedThreadCollection....").ifPresent(System.out::println); this.wait(); } blockedThreadCollection.remove(Thread.currentThread()); this.initValue = true; } @Override public synchronized void unlock() { this.initValue = false; Optional.of(Thread.currentThread().getName() + " release the lock monitor....").ifPresent(System.out::println); this.notifyAll(); } @Override public Collection<Thread> getBlockedThread() { return Collections.unmodifiableCollection(blockedThreadCollection); } @Override public int getBlockedSize() { return blockedThreadCollection.size(); } @Override public void lock(long mills) throws TimeOutException, InterruptedException { return; } }
此处wait()的是this对象,sychronized的也是this对象
测试类
package com.dwz.concurrency.chapter10; import java.util.Optional; import java.util.stream.Stream; /** * 多线程的lock * @author dangwangzhen * */ public class LockTest { private static void work() throws InterruptedException { Optional.of(Thread.currentThread().getName() + " is working...").ifPresent(System.out::println); Thread.sleep(10_000); } public static void main(String[] args) throws InterruptedException { final BooleanLock2 booleanLock = new BooleanLock2(); Stream.of("T1", "T2", "T3", "T4") .forEach(name -> new Thread(() -> { try { booleanLock.lock(); Optional.of(Thread.currentThread().getName() + " have the lock Monitor...").ifPresent(System.out::println); work(); } catch (InterruptedException e) { e.printStackTrace(); } finally { booleanLock.unlock(); } }, name).start() ); Thread.sleep(100); //缺点:该锁可能被其他线程释放(该锁被main线程释放) booleanLock.unlock(); } }
缺点:如果在线程执行过程中锁被main线程释放,不能保证 线程加的锁被线程自己释放
改进方法
package com.dwz.concurrency.chapter10; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Optional; /** * 实现一个显示锁lock,并保证锁是由自己释放 */ public class BooleanLock implements Lock { //The initValue is true indicated the lock have be get. //The initValue is false indicated the lock is free(other thread can get this.) private boolean initValue; //保证该锁只能被当前线程释放 private Thread currentThread; private Collection<Thread> blockedThreadCollection = new ArrayList<>(); public BooleanLock() { this.initValue = false; } @Override public synchronized void lock() throws InterruptedException { while (initValue) { blockedThreadCollection.add(Thread.currentThread()); Optional.of(Thread.currentThread().getName() + " add the blockedThreadCollection....").ifPresent(System.out::println); this.wait(); } blockedThreadCollection.remove(Thread.currentThread()); this.initValue = true; this.currentThread = Thread.currentThread(); } @Override public synchronized void unlock() { if(Thread.currentThread() == currentThread) { this.initValue = false; Optional.of(Thread.currentThread().getName() + " release the lock monitor....").ifPresent(System.out::println); this.notifyAll(); } } @Override public Collection<Thread> getBlockedThread() { return Collections.unmodifiableCollection(blockedThreadCollection); } @Override public int getBlockedSize() { return blockedThreadCollection.size(); } }