可重入不可重入锁,自旋锁,独占锁(写锁),共享锁(读锁),互斥锁,学习案例
程序员文章站
2022-03-27 12:40:58
可重入不可重入锁public class ReenterLockDemo { public static void main(String[] args) { Phone phone = new Phone(); ExecutorService executorService = Executors.newFixedThreadPool(2);// for(int i =0; i < 100; i++){// execu...
可重入不可重入锁
/**
* @ClassName ReenterLockDemo
* @Description 可重入锁(也叫递归锁)
*
* 指的是同一线程 外层函数获得锁之后,内层递归函数仍然能获得该锁的代码
* 在同一个线程的外层方法获取锁的时候,进入内层方法时会自动获得该锁
*
* 也就是说 线程可以进入任何一个他已经拥有的锁所同步着的代码块
**/
public class ReenterLockDemo {
public static void main(String[] args) {
Phone phone = new Phone();
ExecutorService executorService = Executors.newFixedThreadPool(2);
// for(int i =0; i < 100; i++){
// executorService.execute(()-> {
// try {
// phone.sendMsg();
// } catch (Exception e) {
// e.printStackTrace();
// }
// });
// }
for(int i =0; i < 2; i++){
executorService.execute(phone);
}
executorService.shutdown();
}
}
class Phone implements Runnable{
public synchronized void sendMsg() throws Exception{
System.out.println(Thread.currentThread().getName() + "sendMsg");
sendEmail();
}
public synchronized void sendEmail() throws Exception{
System.out.println(Thread.currentThread().getName() + "sendEmail");
}
Lock lock = new ReentrantLock();
@Override
public void run() {
get();
}
public void get(){
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "get");
set();
}finally {
lock.unlock();
}
}
public void set(){
lock.lock();
System.out.println(Thread.currentThread().getName() + "set");
lock.unlock();
}
}
自旋锁
/**
* @ClassName SpinLockDemo
* @Description 自旋锁
*
* 自旋锁是指尝试获取锁的线程不会立即堵塞,而是采用循环的方式尝试去获取锁
* 这样的好处是可以减少线程上下文的切换, 缺点是循环会消耗cpu
**/
public class SpinLockDemo {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
public void myLock(){
Thread thread = Thread.currentThread();
System.out.println(thread.getName() + "\t come in !");
while (!atomicReference.compareAndSet(null,thread)){
// System.out.println("我转!我转!");
}
}
public void myUnLock(){
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread,null);
System.out.println(thread.getName() + "\t myUnLock !");
}
public static void main(String[] args) throws InterruptedException {
SpinLockDemo demo = new SpinLockDemo();
new Thread(() ->{
demo.myLock();
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
demo.myUnLock();
},"AA").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() ->{
demo.myLock();
demo.myUnLock();
},"BB").start();
}
}
独占锁(写锁),共享锁(读锁),互斥锁
/**
* @ClassName ReadWriteLockDemo
* @Description 互斥锁
*
* 多个线程同时读一个资源类没有任何问题,所以为了满足并发量,读取共享资源时,应该可以同时进行
* 但是如果有一个线程尝试去写共享资源时,就不应该有其他的线程去读或者写
* 小总结: 读-读 能共存
* 读-写 不能共存
* 写-写 不能共存
**/
class MyCache{
private volatile Map<String, Object> map = new HashMap<>();
private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public void put(String key, Object value) {
rwLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 正在写入: " + key);
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
map.put(key, value);
System.out.println(Thread.currentThread().getName() + "\t 写入完成 ");
}catch (Exception e){
}finally {
rwLock.writeLock().unlock();
}
}
public void get(String key) {
rwLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "\t 正在读取");
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "\t 读取完成: " + map.get(key));
}catch (Exception e){
}finally {
rwLock.readLock().unlock();
}
}
}
public class ReadWriteLockDemo {
public static void main(String[] args) {
MyCache myCache = new MyCache();
for(int i = 1; i <= 5; i++){
final int ii = i;
new Thread(()-> myCache.put(ii + "", ii + "")
,String.valueOf(i)).start();
}
for(int i = 1; i <= 5; i++){
final int ii = i;
new Thread(()-> myCache.get(ii + "")
,String.valueOf(i)).start();
}
}
}
本文地址:https://blog.csdn.net/qq_38854914/article/details/107379037
上一篇: 通过java导入读取微软项目管理文件
下一篇: 多线程之生产者消费者模型