不使用同步的线程安全队列

时间:2015-12-07 16:05:01

标签: java multithreading

我必须创建一个程序,给定N个线程,这些线程可以从队列中插入或删除元素,但是线程有条件访问队列:

  • 如果只有一个线程试图插入或删除一个元素,它将能够;
  • 如果两个或多个线程同时尝试,则可以执行,下一个将在第一个完成时执行其操作。

我使用synchronized块,就像那样:

import java.util.ArrayList;
import java.util.Random;

public class EditorThread extends Thread {

    static int N = 10; // number of threads
    static queue Q = new queue(); // shared queue
    private int number; //number of the thread

    public EditorThread(int n) {
        number = n;
    }

    @Override
    public void run() {
        Random r = new Random();

        while (true) {
            int t = r.nextInt(2);
            if (t == 1) {
                int value = Q.get();
                if (value == -1) {
                    System.out.println("The Thread " + number + " couldnt get any element (empty queue)");
                }

                else {
                    System.out.println("The Thread " + number + " got the element " + value );
                }
            }

            else {
                int n = r.nextInt(100);
                Q.put(n);
                System.out.println("The Thread " + number + " inserted the element " + n);
            }

        }

    }

    public static void main(String[] args) {

        for (int i = 0; i < N; i++) {
            Thread t = new EditorThread(i);
            t.start();
        }

    }

}

class queue {
    node head;
    node tail;

    queue() {
        head = tail = null;
    }

    public synchronized int get() {
        if (head == null)
            return -1;
        int r = head.value;
        if (head != tail)
            head = head.next;
        else
            head = tail = null;
        return r;
    }

    public synchronized void put(int i) {
        node n = new node(i);
        if (head == null)
            head = tail = n;
        else {
            tail.next = n;
            tail = n;
        }
    }

}

class node {

    int value;
    node next;

    public node(int value) {
        this.value = value;
    }

}

run void很简单,它只是在插入或删除元素时永远循环。

我的问题是,如何在不使用synchronized的情况下遵循这些条件?

如果没有同步块,如何保证互斥?

编辑:我不能使用类似于synchronized的东西(就像锁)

1 个答案:

答案 0 :(得分:0)

不,是的。

从根本上说,您需要使用某种形式的同步来执行此操作。没有它就没办法自己做。

然而,java.util.concurrent包中有一些类可以提供您所需的行为,并尽可能地减少锁定和同步成本。

例如LinkedBlockingQueuehttps://docs.oracle.com/javase/7/docs/api/java/util/concurrent/LinkedBlockingQueue.html

如果你真的想了解这些东西是如何工作的,你还应该阅读非阻塞算法。维基页面是一个好的开始。总的来说,许多非常聪明的人确切地知道他们在做什么,但他们在并发包中工作过。线程很难做对。

https://en.wikipedia.org/wiki/Non-blocking_algorithm