实现一个java锁

AQS是实现java锁的核心,但是实现起来还是仅仅只需继承该类重写它的几个主要方法即可。

1.首先,定义一个同步类,继承AQS。

//这里要有个Sync内部类,实现锁需要继承AQS
private static class MySync extends AbstractQueuedSynchronizer {
/**
* 使用CAS尝试改变同步状态,抢锁就使用cas将当前线程设置状态为1,设置owner为当前线程
* @param arg 设置状态锁必须要设置为1
* @return
*/
@Override
protected boolean tryAcquire(int arg) {
if(arg !=1){
throw new RuntimeException("args 不为1");
}
//使用CAS尝试改变同步状态
if(compareAndSetState(0,1)){
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}

/**
* 释放锁不需要cas操作
* @param arg
* @return
*/
@Override
protected boolean tryRelease(int arg) {
if(getState()==0){
throw new IllegalMonitorStateException();
}
//设置锁不被任何线程持有
setExclusiveOwnerThread(null);
setState(0);
return true;
}

@Override
protected boolean isHeldExclusively() {
return getState()==1;
}
}
2.要实现锁,自然要定义我自己的锁了,如下
/**
* 手动是实现java的锁机制
* 这里主要要实现几个方法:tryLock,lock,unlock
*/
public class MyLock implements Lock {
  
  //这里引用刚才的aqs子类
private MySync mySync=new MySync();

@Override
public void lock() {
mySync.acquire(1);
}

@Override
public boolean tryLock() {
return mySync.tryAcquire(1);
}

@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return mySync.tryAcquireNanos(1,time);
}

@Override
public void unlock() {
mySync.release(1);
}

@Override
public Condition newCondition() {
return null;
}
@Override
public void lockInterruptibly() throws InterruptedException {

}
}
好了,仅仅两个类即可搞定。下面来测试下是否好使。先定义一个线程,使用自己实现的锁
public class MyThread implements Runnable{

MyLock myLock = new MyLock();
@Override
public void run() {
try {
myLock.lock();
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+"\t"+"正在执行..."+ DateUtil.now());
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
myLock.unlock();
}

}
}

最后,测试类如下,我们开启10个线程小试一把,
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();

for (int i = 0; i < 10; i++) {
new Thread(myThread,i+"-thread").start();
}
}
}
输出结果截图如下:

而注销掉加锁的两行,则

 

效果很明显了


转载于:https://www.cnblogs.com/hd-zg/p/11202203.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我可以为你提供一些有关如何使用Java实现分布式的信息。首先,您可以使用Java中的定机制,例如java.util.concurrent.locks.Lock,来实现分布式。其次,您可以使用分布式系统中常见的分布式编程模式,例如Two-Phase-Commit(2PC),分布式(DLM)和Zookeeper等,来解决分布式问题。 ### 回答2: Java实现分布式主要可以使用如下几种方式: 1. 基于数据库:可以通过数据库的行级实现分布式。具体实现方式是,在数据库中创建一张表,其中每个对应于一个唯一的资源。当需要获取时,可以在表中插入对应的资源记录,并使用数据库的唯一索引来保证该资源的唯一性。其他线程或进程需要获取时,会尝试插入相同的资源记录,如果插入失败(唯一索引冲突),则说明已经被其他线程或进程获取。 2. 基于Redis:可以利用Redis的原子操作来实现分布式。具体实现方式是,通过使用Redis的SET命令设置一个key,其中key的值可以被设置为当前线程的唯一标识。其他线程或进程需要获取时,会尝试设置相同的key,如果设置成功,则说明获取到了。 3. 基于ZooKeeper:可以利用ZooKeeper的顺序节点来实现分布式。具体实现方式是,每个线程或进程尝试在指定路径下创建一个临时顺序节点,并获取所有的子节点,如果当前节点是最小的子节点,则说明获取到了,否则监听前一个节点的删除事件,等待被唤醒。 无论是哪种方式,需要注意的是,获取的过程应该是原子的,避免获取失败时出现竞态条件。此外,还需要考虑的超时机制,避免被长时间占用而导致死。 ### 回答3: Java 实现分布式可以借助于 Redis、Zookeeper 或数据库等工具实现。 在 Redis 中,可以使用 SETNX (SET if Not Exists) 命令来实现。当一个线程需要获取时,可以执行 `SETNX lockKey 1`,如果返回的结果是 1,表示获取成功;如果返回的结果是 0,表示已经被其他线程占用。在执行完业务逻辑后,需要释放,可以执行 `DEL lockKey` 命令。 在 Zookeeper 中,可以使用节点的特性来实现分布式。创建一个临时顺序节点,当一个线程需要获取时,可以在指定的路径下创建一个节点。然后通过获取子节点列表并判断自己是否为最小节点来判断是否获取到。如果自己不是最小节点,则监听并等待前一个节点被删除,然后再尝试获取。释放时,只需要删除自己创建的节点。 在数据库中,可以使用数据库事务和唯一索引来实现分布式。创建一张表,其中包含一个键的唯一索引列,当一个线程需要获取时,可以通过尝试插入一行数据来获得。如果插入成功,表示获取成功;如果插入失败,表示已经被其他线程占用。在执行完业务逻辑后,通过删除对应的行来释放。 无论使用哪种方式实现分布式,都需要注意的超时和宕机问题,以及避免死和并发竞争的情况的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值