java - 线程同步-线程何时释放对象上的锁

标签 java multithreading thread-synchronization

public class MyStack2 {
    private int[] values = new int[10];
    private int index = 0;

    public synchronized void push(int x) {
        if (index <= 9) {
            values[index] = x;
            Thread.yield();
            index++;
        }
    }

    public synchronized int pop() {
        if (index > 0) {
            index--;
            return values[index];
        } else {
            return -1;
        }
    }

    public synchronized String toString() {
        String reply = "";
        for (int i = 0; i < values.length; i++) {
            reply += values[i] + " ";
        }
        return reply;
    }
}

public class Pusher extends Thread {
    private MyStack2 stack;

    public Pusher(MyStack2 stack) {
        this.stack = stack;
    }

    public void run() {
        for (int i = 1; i <= 5; i++) {
            stack.push(i);
        }
    }
}

public class Test {
    public static void main(String args[]) {
        MyStack2 stack = new MyStack2();
        Pusher one = new Pusher(stack);
        Pusher two = new Pusher(stack);
        one.start();
        two.start();
        try {
            one.join();
            two.join();
        } catch (InterruptedException e) {
        }
        System.out.println(stack.toString());
    }
}

由于 MyStack2 类的方法是同步的,我期望输出为 1 2 3 4 5 1 2 3 4 5。但输出是不确定的。通常它给出:1 1 2 2 3 3 4 4 5 5

据我了解,当线程 1 启动时,它会获取 push 方法上的锁。在 push() 线程中,一个让步一段时间。但是当 yield() 被调用时它会释放锁吗?现在当线程二启动时,线程二会在线程一完成执行之前获取锁吗?有人能解释一下线程一什么时候释放堆栈对象上的锁吗?

最佳答案

synchronized 方法只会在它正在执行时阻止其他线程执行它。一旦它返回,其他线程就可以(并且通常会立即)获得访问权限。

获取 1 1 2 2 ... 的场景可能是:

  1. 线程 1 调用 push(1) 并被允许进入。
  2. 线程 2 调用 push(1) 并在线程 1 使用它时被阻塞。
  3. 线程 1 退出 push(1)
  4. 线程 2 可以访问 push 并推送 1,但同时线程 1 调用 push(2)

结果 1 1 2 - 您可以清楚地看到它是如何继续的。

关于java - 线程同步-线程何时释放对象上的锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26237662/

相关文章:

java 字符串和哈希集成员资格匹配

java - 迭代器 hasnext() 返回 true 但 next() 抛出 NoSuchElementException

java - 使用通过 JAVA 代码生成的 token 时,oauth 的凭据无效(失败)

C# .Net 4.0 控制台应用程序 - 如何在所有线程完成之前保持事件状态?

c# - 从异步方法更新 GUI

java - 检查Java中代码块是否正确嵌套?

javascript - 是否可以将传输的 ArrayBuffer 返回原始类型数组?

c++ - 不同线程中的 qt 同时 MySQL 查询 = 崩溃

Java在自定义方法中同时执行3个方法并从run方法中获取值

c# - 如何在WPF中使用ISynchronizeInvoke接口(interface)?