今天学习了java的lock和sychronized的区别,所以实践一下。
lock()方法实现懒汉式单例
package domain;
import java.util.concurrent.locks.ReentrantLock;
public class Singleton {
private static volatile Singleton instance;
private static ReentrantLock reentrantLock = new ReentrantLock();
private Singleton() {
}
public static Singleton getInstance() {
//double check
if (instance == null) {
try {
reentrantLock.lock();
if (instance == null) {
instance = new Singleton();
}
} finally {
reentrantLock.unlock();
}
}
return instance;
}
}
condition实现进程通信
交替打印数字
package examples;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private static ReentrantLock reentrantLock = new ReentrantLock();
private static Condition condition1 = reentrantLock.newCondition();
private static Condition condition2 = reentrantLock.newCondition();
public static void main(String[] args) {
new Thread(() -> {
try {
reentrantLock.lock();
for (int i = 1; i < 10; ++i) {
System.out.println(i);
condition2.signal();
condition1.await();
}
condition2.signal();//退出最后一个等待
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}).start();
new Thread(() -> {
try {
reentrantLock.lock();
for (int i = 21; i < 30; ++i) {
System.out.println(i);
condition1.signal();
condition2.await();
}
condition1.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}).start();
}
}
输出结果:
1
21
2
22
3
23
4
24
5
25
6
26
7
27
8
28
9
29
使用lockInterruptibly()方法
lockInterruptibly()
允许在等待时由其它线程调用等待线程的Thread.interrupt()
方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个InterruptedException
。 lock()
方法不允许Thread.interrupt
中断,即使检测到Thread.isInterrupted
,一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功后再把当前线程置为interrupted
状态,然后再中断线程。
package examples;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private static ReentrantLock reentrantLock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
try {
reentrantLock.lockInterruptibly();
for (int i = 0; i < 10; ++i) {
Thread.sleep(3000);
System.out.println("线程" + Thread.currentThread().getName() + ": " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}, "1");
t1.start();
//等5秒
Thread.sleep(5000);
Thread t2 = new Thread(() -> {
try {
reentrantLock.lock();
System.out.println("线程" + Thread.currentThread().getName() + "获取到锁");
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}, "2");
t2.start();
//再等5秒
Thread.sleep(5000);
//等不及了
System.out.println("中断t1");
t1.interrupt();
}
}
输出结果:
线程1: 0
线程1: 1
线程1: 2
中断t1
线程2获取到锁
java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at examples.ReentrantLockExample.lambda$main$0(ReentrantLockExample.java:13)
at java.base/java.lang.Thread.run(Thread.java:830)
tryLock()应用
忽略重复触发
tryLock()
功能:如果已经获得锁立即返回false,起到防止重复而忽略的效果
package examples;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private static ReentrantLock reentrantLock = new ReentrantLock();
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (reentrantLock.tryLock()) {
try {
System.out.println("线程" + Thread.currentThread().getName() + "获得锁");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
}
};
for (int i = 0; i < 10; ++i) {
new Thread(runnable, "" + i).start();
}
}
}
输出结果:
线程0获得锁
带参数tryLock:超时放弃
package examples;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
private static ReentrantLock reentrantLock = new ReentrantLock();
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
if (reentrantLock.tryLock(5, TimeUnit.SECONDS)) {
try {
System.out.println("线程" + Thread.currentThread().getName() + "获取到锁");
Thread.sleep(10000);
} finally {
reentrantLock.unlock();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread(runnable, "1").start();
new Thread(runnable, "2").start();//这个线程会超时,获取不到锁
}
}
输出结果:
线程1获取到锁