Java多线程-01.ReentrantLock、ReadWriteLock

CAS

compare and set

cas(V, expected, newValue)

我们要修改V的值为newValue,如果它是我们期望的值expected,则修改,
否则重新比较或失败。
CAS是CPU层面的支持,不会被打断。

开发工作中,如果需要频繁地加synchronized锁,可以通过原子的Atomic类来实现,
这些Atomic开头的类的内部自动就带了锁,当然这些锁挺不是重量级synchronized锁,
而是通过CAS操作来实现的(号称无锁)。
AtomicInteger就是concurrent包下的一个原子的Integer类型,它是线程安全的。

基于CAS的锁

ReentrantLock可重入锁

package com.duohoob.jvm.thread.cas;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 可重入锁
 * 
 * 注意:必须要手动释放锁
 * @author yangwei
 *
 */
public class ReentrantLockTest {

	Lock lock = new ReentrantLock(true); // true代表公平锁,即当一个新的线程过来的时候,会进入阻塞队列等待,否则直接抢
	
	void m1() {
		// 加try-finally是为了保证异常情况下也能释放锁
		try {
			lock.lock(); // 相当于synchronized (this)锁住当前对象
			for (int i = 0; i < 10; i++) {
				System.out.print("m1:" + i); // 这里没有换行
				m2(); // m2也持有当前对象的锁,如果能执行说明ReentrantLock是可重入的
				TimeUnit.SECONDS.sleep(1);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	void m2() {
		try {
			lock.lock();
			System.out.println(); // 输出换行
		} finally {
			lock.unlock();
		}
	}

	void m3() {
		boolean locked = false;
		try {
			locked = lock.tryLock(3, TimeUnit.SECONDS); // 尝试申请锁,3秒之后没有拿到则不再阻塞,继续执行
			System.out.println("m3 locked:" + locked);
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			if (locked) {
				lock.unlock();
			}
		}
	}
	
	public static void main(String[] args) {
		ReentrantLockTest rlt = new ReentrantLockTest();
		new Thread(rlt::m1).start();
		new Thread(rlt::m3).start();
	}
	
}

输出

m1:0
m1:1
m1:2
m3 locked:false
m1:3
m1:4
m1:5
m1:6
m1:7
m1:8
m1:9

ReadWriteLock读写锁

package com.duohoob.jvm.thread.cas;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁
 * @author yangwei
 *
 */
public class ReadWriteLockTest {

	static ReentrantLock lock = new ReentrantLock();
	static ReadWriteLock rwLock = new ReentrantReadWriteLock();
	static Lock readLock = rwLock.readLock(); // 共享锁,其它线程还可以加读锁,但是不能加写锁
	static Lock writeLock = rwLock.writeLock(); // 排它锁,其它线程不可以加任何锁
	
	static void read(Lock lock) {
		try {
			lock.lock();
			Thread.sleep(1000);
			System.out.println("read over!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}
	
	static void write(Lock lock) {
		try {
			lock.lock();
			Thread.sleep(1000);
			System.out.println("write over!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			lock.unlock();
		}
	}

	public static void main(String[] args) {
		// Runnable readR = ()-> read(lock); // 这种方式相当于synchronized,其它线程都会被阻塞
		Runnable readR = ()-> read(readLock);
		
		// Runnable writeR = ()->write(lock);
		Runnable writeR = ()->write(writeLock);
		
		for (int i = 0; i < 8; i++) {
			new Thread(readR).start();
		}
		
		for (int i = 0; i < 2; i++) {
			new Thread(writeR).start();
		}
	}
	
}

输出

read over!
read over!
read over!
read over!
read over!
read over!
read over!
read over!
write over!
write over!

如果传入ReentrantLock需要10秒以上才能输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值