自定义非公平锁-demo

说明

当调用lock时
先竞争资源看看能否获得锁,如果不能则进入队尾进行排队,并且该线程阻塞,以免一直在while循环中运行占用cpu资源
当调用unlock时
进行释放锁操作,先把当前线程的资源释放,然后再唤醒队列的头部
因为当竞争锁时如果直接获得锁,不会进入排队队列,因此释放锁时需要判断

逻辑

在这里插入图片描述

代码

功能代码

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;


class Node{
	private volatile Thread thread= null;
	private volatile boolean isWait = false;
	
	Node(Thread thread,boolean isWait){
		this.thread = thread;
		this.isWait = isWait;
	}

	public Thread getThread() {
		return thread;
	}

	public boolean isWait() {
		return isWait;
	}

	public void setWait(boolean isWait) {
		this.isWait = isWait;
	}
	
	
}

public class KLock {
	//状态标记
	private AtomicInteger state = new AtomicInteger(0);
	//锁排队队列
	private  LinkedList<Node> list = new LinkedList<>();
	//当前线程
	private transient volatile Thread currThread = null;
	
	public void lock() {
		//在获取锁之前先进行竞争,如果获得锁立即返回,否则则排队
		if(tryAcquire() || acquire(addWait())) {
		}
	}
	
	public boolean unLock() {
		int c = state.get() - 1;
		if(Thread.currentThread() != currThread) {
			throw new RuntimeException("线程不匹配");
		}
		
		boolean flag = false;
		if(c == 0) {
			currThread = null;
			flag = true;
			if(list.peek().getThread() == Thread.currentThread()) {
				list.pop();
			}
		}
		state.set(c);
		if(flag && list.peek() != null) {
			//唤醒头部
			LockSupport.unpark(list.peek().getThread());
		}
		
		return flag;
	}

	
	/**
	 * 加入排队队列
	 * 当多个线程加入队列时,有可能造成数据漏掉
	 * 因此需要线程安全操作
	 * @return
	 */
	private synchronized Node addWait() {
		Node node = new Node(Thread.currentThread(),false);
		list.addLast(node);
		return node;
	}
	
	/**
	 * 请求资源
	 * @param node
	 * @return
	 */
	private boolean acquire(Node node) {
		while(true) {
			if(list.peek() == node && tryAcquire()) {
				return true;
			}
			//挂起
			if(!node.isWait()) {
				node.setWait(true);
				LockSupport.park();
			}
			
		}
	}
	
	/**
	 * 尝试获取资源
	 * @return
	 */
	private boolean tryAcquire() {
		//获取锁
		Thread thread = Thread.currentThread();
		int c = state.get();
		if(c == 0) {
			//当状态位为0则获取
			if(state.compareAndSet(0, 1)) {
				currThread = thread;
				return true;
			}
		}
		
		//可重入
		if(thread == currThread) {
			c = c + 1;
			state.set(c);
			return true;
		}
		return false;
	}
	
	
}

测试代码

/**
 * 测试代码
 */
public class Test {
	public static void main(String[] args) {
		KLock lock = new KLock();
		
		for (int i = 1; i <= 50; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					lock.lock();
					try {
						System.out.println(Thread.currentThread().getName());
						Thread.sleep(1000);
					} catch (Exception e) {
						e.printStackTrace();
					}finally {
						lock.unLock();
					}
					
				}
			},"线程-" + i).start();
		}
	}

}

结果截图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值