ReentrantLock和synchronized区别
- 作用跟synchronized 锁一样
- reentrantlock 底层是 cas (值,期望,预期) synchronized 底层锁升级
- reentrantlock 可以tryLock 尝试锁
a. 如果在某时间段内获取到锁,就执行
b. 如果拿不到锁,不需要跟synchronized一样wait,可以直接跳过,继续执行代码 - 需要手动释放锁,必须try catch finally lock.unlock
- synchronized 自动释放锁
- reentrantlock 可以打断锁 interrupt 停止等待,跳过被锁部分,执行别的代码
- reentrantlock 可以是公平锁, synchronized 只能是竞争锁
多线程的锁是加在对象上面的,放在对象的markworld上面,当线程来的时候,看对象上的markworld上的值是否是该线程,是执行,不是,等待
该方法测试 lock锁 锁重入 trylock(返回时间到了,是否拿到锁)
public class Thread_09_ReenTrantLock {
LongAdder longAdder = new LongAdder();
Lock lock = new ReentrantLock();
private void insert(){
try{
lock.lock(); //查看对象上的markworld 是否是该请求的线程
for (int i = 0; i < 10; i++) {
Thread.sleep(300);
longAdder.increment();
System.out.println(longAdder);
if(i==2) push();
}
}catch (Exception e){
}finally {
lock.unlock();
}
}
private void push(){
try{
lock.lock(); //查看对象上的markworld 是否是该请求的线程
System.out.println("我是方法二");
}catch (Exception e){
}finally {
lock.unlock();
}
}
private void tryLock(){
boolean trylock = false;
try{
trylock = lock.tryLock(1, TimeUnit.SECONDS); //返回该方法是否获取到锁
if(trylock)
System.out.println("我拿到锁了我是方法三");
}catch (Exception e){
}finally {
if (trylock) lock.unlock();
}
System.out.println("方法三结束");
}
public static void main(String[] args) {
Thread_09_ReenTrantLock t = new Thread_09_ReenTrantLock();
new Thread(t::insert).start();
new Thread(t::push).start();
new Thread(t::tryLock).start();
}
}
reentrantlock 可以被打断的锁 (condition问题,生产者消费者解决)
public class Thread_10_reentrantLock_interrupt {
Lock lock = new ReentrantLock();
public static void main(String[] args) {
Thread_10_reentrantLock_interrupt t = new Thread_10_reentrantLock_interrupt();
//起一个线程,占用锁
new Thread(()->{
sleepMax(t);
}).start();
try{
Thread.sleep(11);
}catch (Exception e){
}
Thread t2 = new Thread(() -> {
method2(t);
});
t2.start();
try{
Thread.sleep(2000);
}catch (Exception e){
}
System.out.println("我受够了无边的等待");
t2.interrupt(); //打断线程二的等待
}
private static void sleepMax(Thread_10_reentrantLock_interrupt t) {
try{
t.lock.lock();
Thread.sleep(Integer.MAX_VALUE);
}catch (Exception e){
}finally {
t.lock.unlock();
}
}
private static void method2(Thread_10_reentrantLock_interrupt t) {
try{
System.out.println("代码二开始执行");
//t.lock.lock();
t.lock.lockInterruptibly();
System.out.println("我想执行代码");
}catch (Exception e){
}finally {
if(t.lock.tryLock()){
t.lock.unlock();
}
System.out.println(t.lock.tryLock()+"我释放锁了");
}
}
}
reentrantlock 公平锁
public class Thread_11_reentrantlock_fair {
Lock lock = new ReentrantLock(true); //默认非公平锁
public void pushValue(String threadName){
for (int i = 0; i < 10; i++) {
lock.lock();
try{
Thread.sleep(1);
}catch (Exception e){
}
System.out.println(threadName+"获取到锁了");
lock.unlock();
}
}
public static void main(String[] args) {
Thread_11_reentrantlock_fair t = new Thread_11_reentrantlock_fair();
new Thread(()->{
t.pushValue("线程1");
}).start();
new Thread(()->{
t.pushValue("线程2");
}).start();
}
}
countDownLatch 管理线程 – 线程门栓
public class Thread_12_countdownlatch {
CountDownLatch count = new CountDownLatch(10);
ReentrantLock lock = new ReentrantLock(true);
AtomicInteger atomicInteger = new AtomicInteger();
private volatile Integer num = 0;
/**
* 加锁方法(公平锁)
*/
private void insertNum2(){
for (int i = 0; i < 1000; i++) {
lock.lock();
num++;
lock.unlock();
}
count.countDown();
}
/**
* 使用线程安全的类 cas
*/
private void insertNum(){
for (int i = 0; i < 1000; i++) {
atomicInteger.incrementAndGet();
}
count.countDown();
}
public static void main(String[] args) {
Thread_12_countdownlatch t = new Thread_12_countdownlatch();
List<Thread> threadList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
threadList.add(new Thread(t::insertNum));
}
threadList.forEach((o)->o.start());
try{
t.count.await();
}catch (Exception e){
}
System.out.println("总数为"+t.atomicInteger);
}
}
countDownLatch 和 Thread.join 区别:
- countDownLatch 比较灵活,可以在任何时间countdown
- 代码里面一定要try catch finally里面 countdown
- 个人喜欢countDownLatch