使用JAVA 2-Threads解决方案进行互斥

时间:2018-01-22 23:59:51

标签: java multithreading mutual-exclusion

我正在尝试使用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++;
        }
    }

}

2 个答案:

答案 0 :(得分:3)

您的代码中存在两个问题。

  1. if(!locked)并且设置locked=true不是原子操作,这是 意味着两个线程可以找到它并未锁定并同时锁定它。
  2. 在变量lockedcurrent上没有同步,所以一个 线程可能无法读取其他线程设置的新值 因为memory barriar
  3. 您可以使用AtomicBooleanvolatile解决此问题:

    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;
        }
    }
}