Peterson算法作为二叉树

时间:2014-02-05 04:12:47

标签: java multithreading algorithm concurrency binary-tree

我目前正在尝试编写一个解决此问题的Java程序。

“推广双线程Peterson锁的另一种方法是在二叉树中安排一些双线程的Peterson锁。假设n是2的幂。每个线程被分配一个叶锁,它与一个共享其他线程。每个锁将一个线程视为线程0,另一个线程视为线程1.“

我觉得我已经解决了,但我的输出并不总是正确的。我怀疑我的问题是在我的锁定方法的for循环中调用经过验证的Peterson锁(Peterson锁没有错误,因为它是为了解决这个问题而提供的)。我基本上构建了一个平衡的二叉树,声明了一个Peterson Algorithm实例的数组,并且,当每个线程进来时,我使用树作为索引并调用Peterson锁。

package mutex;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class tree_lock implements Lock{

int total_instances;
int thread_instances = 0;
int N;
static int cnt = 0;
static int cnt2 = 0;
int flag = 0;
Node root;
Peterson[] PeterInstances;
int[] IncomingThreadIDs;

final private ThreadLocal<Integer> THREAD_ID2 = new ThreadLocal<Integer>(){
    final private AtomicInteger id2 = new AtomicInteger(0);

    protected Integer initialValue(){
        return id2.getAndIncrement();
    }
};


//Constructor   : tree_lock Constructor
//Input         : n, the number of threads
//Descritpion   : Determine number of instances fore each thread, Create IDs for each thread, 
//                Create Balanced Binary Tree of with keys numbered from 0 to n
tree_lock(int n)
{
    N=n;
    int temp = n;
    total_instances = n - 1;
    int[] IDs = new int[total_instances];

    //Determine number of instances of each thread
    while(temp != 1)
    {
        temp /=2;
        thread_instances++;
    }

    PeterInstances = new Peterson[total_instances];
    for(int i = 0; i < total_instances; i++)
    {
        PeterInstances[i] = new Peterson();
    }
    IncomingThreadIDs = new int[n];

    //Create IDs for each thread
    for(int i = 0; i < n;i+=2)
    {
        IncomingThreadIDs[i] = cnt;
        IncomingThreadIDs[i+1] = cnt;

        cnt+=2;
    }
    //Create array with keys for each node in binary tree
    for(int i = 0; i < total_instances;i++)
    {
        IDs[i]=i;
    }
    //Create binary tree with keys from above array
    BuildTree(0,IDs.length-1,IDs);
}

//Function   : BuildTree
//Input      : lowest index of array, high index of array, pointer to array
//Output     : Balanced Binary Tree
//Description: Createds a Balanced Binary Tree
//Credit to: http://linwdav.blogspot.com/2011/06/how-to-build-balanced-binary-search.html
public Node BuildTree(int low, int high, int[] arr)
{       
    if(low > high)
        return null;
    else
    {
        int mid = (low + high)/2;
        Node node = new Node(arr[mid]);
        if(flag == 0)
        {
            root = node;
            flag++;
        }
        node.leftChild = BuildTree(low,(mid-1),arr);
        node.rightChild = BuildTree((mid+1),high,arr);
        return node;
    }

}

//Function    : findNodeParent
//Input       : key for a node
//Output      : key of parent node
//Description : Determines the key for a parent node
public int findNodeParent(int key)
{
    if(root.key == key)
        return  -1;
    Node focusNode = root;

    while(focusNode.leftChild.key != key && focusNode.rightChild.key != key)
    {
        if(key < focusNode.key)
        {
            focusNode = focusNode.leftChild;
        }
        else
        {
            focusNode = focusNode.rightChild;
        }
    }

    return focusNode.key;
}

//Function    : lock
//Description : locks other threads
public void lock()
{
    //get thread ID
    int cnt3 = (THREAD_ID2.get() % N);

    int[] path = new int[thread_instances];
    path[0] = IncomingThreadIDs[cnt3];

    //create path to root node
    for(int k = 1; k < thread_instances; k++)
    {
        path[k] = findNodeParent(path[k-1]);
    }
    //attempt to lock thread up to root node
    for(int i = 0; i < thread_instances; i++)
    {
            //********************************
            //Problem is here!!!!!!!!!!!!!!!
        PeterInstances[path[i]].lock();
            //ThreadID = findNodeParent(ThreadID);
    }

}
//Function   : unlock
//Description : unlocks other threads
public void unlock()
{
    //get thread ID
    int cnt3 = (THREAD_ID2.get() % N);

    //create path to root node
    int[] path = new int[thread_instances];
    path[0] = IncomingThreadIDs[cnt3];

    for(int k = 1; k < thread_instances; k++)
    {
        path[k] = findNodeParent(path[k-1]);
    }

    //attempt to unlock thread to the node
    for(int i = thread_instances - 1; i >= 0; i--)
    {
        PeterInstances[path[i]].unlock();
    }
}

 // Any class implementing Lock must provide these methods
public Condition newCondition() {
throw new java.lang.UnsupportedOperationException();
}
public boolean tryLock(long time,
           TimeUnit unit)
throws InterruptedException {
throw new java.lang.UnsupportedOperationException();
}
public boolean tryLock() {
throw new java.lang.UnsupportedOperationException();
}
public void lockInterruptibly() throws InterruptedException {
throw new java.lang.UnsupportedOperationException();
}

}

class Node
{
int key;

Node leftChild;
Node rightChild;
Node parent;

Node(int key)
{
    this.key = key;

}
}

1 个答案:

答案 0 :(得分:0)

你已经准确地指出了这个问题。您必须使此代码同步。我猜你正在调用的超类lock()是不同步的。

这样做可以解决问题。

synchronized (this){
            PeterInstances[path[i]].lock();
        }

希望它有所帮助。