目录
Lock
一、主程序
二、自定义Lock类
三、实现同步器(服务于自定义的Lock)
四、使用了自定义Lock的任务
五、执行结果
Lock
允许程序员保护一段关键代码,以便一次只有一个线程可以执行该代码块。
lock():当访问临界区时,可以调用此操作。如果有另外的线程要访问该临界区,那么另外的线程会被阻塞,直到它们由锁唤醒才可以访问临界区。unlock():在临界区末尾调用该方法,以允许其他线程访问临界区。
一、主程序
package xyz.jangle.thread.test.n8_9.lock;
import java.util.concurrent.TimeUnit;
/**
* 8.9、自定义Lock类
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月7日 下午7:33:31
*
*/
public class M {
public static void main(String[] args) {
var lock = new MyLock();
for (int i = 0; i < 10; i++) {
var task = new Task(lock, "Task-" + i);
var thread = new Thread(task);
thread.start();
}
// 用tryLock尝试获取锁,每一秒一次,直到成功
boolean value;
do {
try {
value = lock.tryLock(1, TimeUnit.SECONDS);
if (!value) {
System.out.println("M: 尝试获取锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
value = false;
}
} while (!value);
System.out.println("M: 成功获得锁");
lock.unlock();
System.out.println("M: 程序结束");
}
}
二、自定义Lock类
package xyz.jangle.thread.test.n8_9.lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
/**
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月7日 下午7:42:38
*
*/
public class MyLock implements Lock {
private final AbstractQueuedSynchronizer sync;
public MyLock() {
super();
sync = new MyAbstractQueuedSynchronizer();
}
@Override
public void lock() {
sync.acquire(1);
}
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
@Override
public boolean tryLock() {
try {
return sync.tryAcquireNanos(1, 1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
return false;
}
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, TimeUnit.NANOSECONDS.convert(time, unit));
}
@Override
public void unlock() {
sync.release(1);
}
@Override
public Condition newCondition() {
return sync.new ConditionObject();
}
}
三、实现同步器(服务于自定义的Lock)
package xyz.jangle.thread.test.n8_9.lock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* 实现同步器
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月7日 下午7:37:11
*
*/
@SuppressWarnings("serial")
public class MyAbstractQueuedSynchronizer extends AbstractQueuedSynchronizer {
private final AtomicInteger state;
public MyAbstractQueuedSynchronizer() {
super();
state = new AtomicInteger(0);
}
@Override
protected boolean tryAcquire(int arg) {
return state.compareAndSet(0, 1);
}
@Override
protected boolean tryRelease(int arg) {
return state.compareAndSet(1, 0);
}
}
四、使用了自定义Lock的任务
package xyz.jangle.thread.test.n8_9.lock;
import java.util.concurrent.TimeUnit;
/**
* 使用自定义Lock的任务
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月8日 上午9:20:41
*
*/
public class Task implements Runnable {
private final MyLock lock;
private final String name;
public Task(MyLock lock, String name) {
super();
this.lock = lock;
this.name = name;
}
@Override
public void run() {
lock.lock();
System.out.println("Task:" + name + " 开始加锁");
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("Task:" + name + "释放锁");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
五、执行结果
Task:Task-0 开始加锁
M: 尝试获取锁
Task:Task-0释放锁
Task:Task-6 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-6释放锁
Task:Task-7 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-7释放锁
Task:Task-4 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-4释放锁
Task:Task-3 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-3释放锁
Task:Task-1 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-1释放锁
Task:Task-8 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-8释放锁
Task:Task-2 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-2释放锁
Task:Task-9 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-9释放锁
Task:Task-5 开始加锁
M: 尝试获取锁
M: 尝试获取锁
Task:Task-5释放锁
M: 成功获得锁
M: 程序结束