我正在尝试使用LockOne(互斥)算法实现双线程解决方案。实现这个算法,我正在尝试找出一个定义我自己的锁方法的线程,但我没有得到所需的输出。当我运行程序..我得到的输出是“线程0锁定”和“线程-1锁定”..任何人都可以让我知道我哪里出错了?我的代码在下面给出
public class Main {
static MyLock lock=null;
static int count=0;
public static void main(String[] args) throws InterruptedException {
Thread[] threads=new Thread[2];
threads[0]=new Thread(new MyThread());
threads[1]=new Thread(new MyThread());
lock=new MyLock();
threads[0].start();
threads[1].start();
threads[0].join();
threads[1].join();
System.out.println(count);
}
}
public class MyLock{
private boolean locked=false;
private String current;
public void lock() {
if(!locked){
locked=true;
current=Thread.currentThread().getName();
}
System.out.println(Thread.currentThread().getName()+" locked");
while(locked && current!=Thread.currentThread().getName());
}
public void unlock() {
System.out.println(Thread.currentThread().getName()+" unlocked");
locked=false;
}
}
public class MyThread implements Runnable{
@Override
public void run() {
int i=1;
while(i<=100){
Main.lock.lock();
Main.count++;
Main.lock.unlock();
i++;
}
}
}
答案 0 :(得分:3)
您的代码中存在两个问题。
if(!locked)
并且设置locked=true
不是原子操作,这是
意味着两个线程可以找到它并未锁定并同时锁定它。locked
和current
上没有同步,所以一个
线程可能无法读取其他线程设置的新值
因为memory barriar。您可以使用AtomicBoolean
和volatile
解决此问题:
import java.util.concurrent.atomic.AtomicBoolean;
public class MyLock{
private AtomicBoolean locked = new AtomicBoolean(false);
private volatile String current;
public void lock() {
for (;;) {
if(!locked.get()){
if (locked.compareAndSet(false, true)) {
current = Thread.currentThread().getName();
System.out.println(current + " locked");
return;
}
}
}
}
public void unlock() {
System.out.println(current + " unlocked");
locked.set(false);
}
}
答案 1 :(得分:1)
另一种解决方案,如果您需要使用公平收购政策进行可重入锁定:
public class MyLock
{
private String holder;
private Queue<Long> next = new ConcurrentLinkedQueue<>();
private Object syncLock = new Object();
public void lock()
{
Long threadId = Thread.currentThread().getId();
this.next.add(threadId);
boolean acquired = false;
while (!acquired)
{
synchronized (this.syncLock)
{
if (this.holder == null)
{
if (this.next.peek() == threadId)
{
this.holder = Thread.currentThread().getName();
System.out.println(this.holder + " locked");
acquired = true;
}
}
else
{
if (this.holder.equals(Thread.currentThread().getName()))
{
acquired = true;
}
}
}
}
this.next.remove(threadId);
}
public void unlock()
{
synchronized (this.syncLock)
{
System.out.println(Thread.currentThread().getName() + " unlocked");
this.holder = null;
}
}
}