`

java读写锁升级与降级、并会发现死锁。抛出异常

    博客分类:
  • java
 
阅读更多
package com.huawei.test;

import java.util.HashMap;
import java.util.Map;


public class SpinReadWriteLock {
private volatile Thread writeThread = null;
private volatile int writeCount = 0;
//标记已经获取读lock的线程想要获取写lock   但被阻止了(因各种原因)
private volatile Thread readRequestWriteLockingThread = null;
private volatile Map<Thread, Integer> readThread = new HashMap<>();
private Object read = new Object();

public void readLock() throws InterruptedException {
Thread current = Thread.currentThread();
synchronized (read) {
while (writeThread != null && writeThread != current) {
read.wait();
}
Integer readCount = readThread.get(current);
if (readCount == null) {
// 表示当前线程正在持有锁 对锁持有的次数+1
readCount = 0;
}
readCount++;
readThread.put(current, readCount);
}
}

public void readUnlock() {
synchronized (read) {
Thread current = Thread.currentThread();
Integer readCount = readThread.get(current);
if (readCount <= 1) {
readThread.remove(current);
read.notifyAll();
return;
}
readCount--;
readThread.put(current, readCount);
}
}

public void writeLock() throws InterruptedException, DeadLockException {

Thread current = Thread.currentThread();
synchronized (read) {
while ((writeThread != null && writeThread != current)
//写锁被别的线程持有
|| readThread.size() > 1
//或者有多余一个的读锁持者
|| (readThread.size()==1 && !readThread.containsKey(current))
//或者有一个读锁持有者   但不是自己
) {
if(readRequestWriteLockingThread != null && readRequestWriteLockingThread != current)
throw new DeadLockException();
readRequestWriteLockingThread = current;
read.wait();
}
writeThread = current;
writeCount++;
}
}

public void writeUnLock() {

Thread current = Thread.currentThread();
if(current != writeThread)
//
return ;
if (writeCount == 1) {

synchronized (read) {
writeCount = 0;
writeThread = null;
read.notifyAll();
return;
}
}
writeCount--;
}

public static void main(String[] args) {

for (int i = 0; i < 10; i++) {

// new Thread(new Read()).start();
// new Thread(new Write()).start();
new Thread(new DeadReadWrite()).start();
}
}

public final static SpinReadWriteLock READ_WRITE_LOCK = new SpinReadWriteLock();
public static class Read implements Runnable{

@Override
public void run() {

try {

READ_WRITE_LOCK.readLock();
System.out.println(Thread.currentThread().getName() + "获取到了读锁");
Thread.sleep(100);

} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName() + "获取到了放弃读锁");
READ_WRITE_LOCK.readUnlock();
}

}
}
public static class Write implements Runnable{

@Override
public void run() {

try {
System.out.println(Thread.currentThread().getName() + "准备获取写锁");
READ_WRITE_LOCK.writeLock();
System.out.println(Thread.currentThread().getName() + "获取到了写锁");
Thread.sleep(200);

} catch (InterruptedException | DeadLockException e) {
System.out.println(Thread.currentThread().getName() + e.getLocalizedMessage());
} finally {
System.out.println(Thread.currentThread().getName() + "准备放弃写锁");
READ_WRITE_LOCK.writeUnLock();
}

}
}
public static class ReadWrite implements Runnable{

@Override
public void run() {


try {

READ_WRITE_LOCK.writeLock();
System.out.println(Thread.currentThread().getName() + "获取到了写锁");
Thread.sleep(20);
READ_WRITE_LOCK.readLock();
System.out.println(Thread.currentThread().getName() + "获取到了读锁");
Thread.sleep(20);
READ_WRITE_LOCK.writeLock();
System.out.println(Thread.currentThread().getName() + "获取到了写锁");
Thread.sleep(20);
READ_WRITE_LOCK.readLock();
System.out.println(Thread.currentThread().getName() + "获取到了读锁");
Thread.sleep(20);
READ_WRITE_LOCK.writeLock();
System.out.println(Thread.currentThread().getName() + "获取到了写锁");
Thread.sleep(20);
READ_WRITE_LOCK.readLock();
System.out.println(Thread.currentThread().getName() + "获取到了读锁");
Thread.sleep(20);

} catch (InterruptedException | DeadLockException e) {
System.out.println(Thread.currentThread().getName() + e.getLocalizedMessage());
} finally {
System.out.println(Thread.currentThread().getName() + "准备放弃写锁");
READ_WRITE_LOCK.writeUnLock();
System.out.println(Thread.currentThread().getName() + "准备放弃读锁");
READ_WRITE_LOCK.readUnlock();
System.out.println(Thread.currentThread().getName() + "准备放弃写锁");
READ_WRITE_LOCK.writeUnLock();
System.out.println(Thread.currentThread().getName() + "准备放弃读锁");
READ_WRITE_LOCK.readUnlock();
System.out.println(Thread.currentThread().getName() + "准备放弃写锁");
READ_WRITE_LOCK.writeUnLock();
System.out.println(Thread.currentThread().getName() + "准备放弃读锁");
READ_WRITE_LOCK.readUnlock();
}

}
}

public static class DeadReadWrite implements Runnable{

@Override
public void run() {
try {

READ_WRITE_LOCK.readLock();
System.out.println(Thread.currentThread().getName() + "获取到了读锁");
Thread.sleep(200);
READ_WRITE_LOCK.writeLock();
System.out.println(Thread.currentThread().getName() + "获取到了写锁");

} catch (InterruptedException | DeadLockException e) {
StackTraceElement[] ee = e.getStackTrace();
System.out.println(Thread.currentThread().getName() +"抛出异常");
for (StackTraceElement stackTraceElement : ee) {
System.out.println(stackTraceElement.toString());
}

} finally {
System.out.println(Thread.currentThread().getName() + "准备放弃写锁");
READ_WRITE_LOCK.writeUnLock();
System.out.println(Thread.currentThread().getName() + "准备放弃读锁");
READ_WRITE_LOCK.readUnlock();
}

}
}
public static class UnDeadReadWrite implements Runnable{

@Override
public void run() {
try {


READ_WRITE_LOCK.writeLock();
System.out.println(Thread.currentThread().getName() + "获取到了写锁");
Thread.sleep(200);
READ_WRITE_LOCK.readLock();
System.out.println(Thread.currentThread().getName() + "获取到了读锁");


} catch (InterruptedException | DeadLockException e) {
System.out.println(Thread.currentThread().getName() + e.getLocalizedMessage());
} finally {
System.out.println(Thread.currentThread().getName() + "准备放弃读锁");
READ_WRITE_LOCK.readUnlock();
System.out.println(Thread.currentThread().getName() + "准备放弃写锁");
READ_WRITE_LOCK.writeUnLock();

}

}
}

public static class DeadLockException extends Exception{


}
}
分享到:
评论

相关推荐

    java多线程-读写锁原理

    这样即使在try块中有异常抛出,也能确保锁最终会被释放,防止资源被不当占用。 读写锁的实现中,如上述示例所示,通过`wait()`和`notifyAll()`方法管理线程的等待与唤醒。读锁的获取允许在没有写锁请求和写锁持有时...

    读写互斥封装

    6. **锁的升级和降级**:在某些高级读写锁实现中,允许在持有读锁的情况下升级为写锁(如果当前没有其他读写锁),并在写操作后降级回读锁。这是一种优化策略,可以在某些场景下提高效率。 7. **异常处理**:类可能...

    自己动手写一把可重入锁测试案例

    6. **锁升级与降级**:在某些情况下,我们可能需要将可重入锁升级为读写锁,以支持多个线程同时读取资源。这涉及到更复杂的设计,但原理类似。 7. **中断处理**:支持锁的中断,当线程在等待锁时,如果被中断,应该...

    互联网高频Java后端面试题20道(适合1~3年)V1.0.27.docx

    通过抛出和捕获异常,可以将错误处理与正常代码分离,提高程序的可读性和稳定性。合理使用异常处理能确保程序在遇到错误时能够优雅地处理,而不是突然崩溃。 问题 15:什么是数据库事务?ACID 属性是什么? 数据库...

    Java架构面试专题汇总(含答案)和学习笔记

    - **异常处理**:异常的分类、捕获与抛出、自定义异常的使用。 2. **Java进阶** - **反射机制**:Class类的使用、动态创建对象、访问私有属性和方法。 - **设计模式**:工厂模式、单例模式、观察者模式、装饰器...

    java程序员面试大纲错过了金三银四你还要错过2018吗.docx

    10. **异常分类及处理机制**:Java中的异常分为运行时异常和检查型异常,前者无需显式捕获或声明,后者必须处理或向上层抛出。 11. **wait和sleep的区别**:`wait()`方法使线程进入等待状态并释放锁,而`sleep()`...

    大厂面试题.................................................

    4. **异常处理**:异常的分类(检查异常和运行时异常)、捕获与抛出、自定义异常,以及finally块的使用。 5. **IO流**:字节流、字符流、缓冲流、转换流、对象流,以及NIO(New IO)和NIO.2(Java 7引入的 Channels...

    C#多线程编程之使用ReaderWriterLock类实现多用户读与单用户写同步的方法

    如果在1000毫秒内无法获取锁,程序会抛出ApplicationException异常。 ReaderWriterLock类提供了一种优化的并发控制策略,尤其适合于读多写少的场景。相比于Mutex和Monitor,ReaderWriterLock允许更多的并发读取,...

Global site tag (gtag.js) - Google Analytics