gpt4 book ai didi

java - 为什么我的两个简单 Java 线程没有得到交错访问?

转载 作者:行者123 更新时间:2023-12-03 12:47:35 24 4
gpt4 key购买 nike

我已经阅读了有关线程交错和 Java 线程调度的文章,但我不明白为什么我的两个简单的 Java 线程(针对独占资源运行)在某种程度上不能交错访问资源。

在下面的代码中,我有一个 Resource 类,其唯一的静态 access() 方法包含一个同步块(synchronized block)。我只是在 main 中创建并启动两个 MyThread 实例,每个线程循环重复调用 Resource.access()。每次访问都会 hibernate 1 秒,然后释放资源。

public class X {
public static void main(String[] args) {
System.out.println("Creating threads");

Thread t1 = (new Thread(new MyThread()));
System.out.println(String.format("Thread t1 id = %d",
t1.getId()));

Thread t2 = (new Thread(new MyThread()));
System.out.println(String.format("Thread t2 id = %d",
t2.getId()));

System.out.println("Starting threads");
t1.start();
t2.start();
}
}

class MyThread implements Runnable {
@Override
public void run () {
for (int i = 0; i <= 5; i++) {
Resource.access();
}
System.out.println(String.format("Thread %d completed",
Thread.currentThread().getId()));
}
}

class Resource {
private static Object monitor = new Object();

public static void access() {
synchronized (monitor) {
System.out.println(String.format(
"Thread %d accessing resource",
Thread.currentThread().getId()));
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
System.exit(1);
}
System.out.println(String.format(
"Thread %d leaving resource",
Thread.currentThread().getId()));
}
}
}

然而,无论我尝试什么,MyThread 实例的循环首先开始(上例中的 t1)在另一个 MyThread 实例(上例中的 t2)获得对资源的任何访问之前完成对资源的所有访问.这是输出:

创建线程
线程 t1 id = 12
线程 t2 id = 13
启动线程
线程 12 访问资源
线程 12 离开资源
线程 12 访问资源
线程 12 离开资源
线程 12 访问资源
线程 12 离开资源
线程 12 访问资源
线程 12 离开资源
线程 12 访问资源
线程 12 离开资源
线程 12 访问资源
线程 12 离开资源
线程 13 正在访问资源
线程 12 完成
线程 13 离开资源
线程 13 正在访问资源
线程 13 离开资源
线程 13 正在访问资源
线程 13 离开资源
线程 13 正在访问资源
线程 13 离开资源
线程 13 正在访问资源
线程 13 离开资源
线程 13 正在访问资源
线程 13 离开资源
线程 13 完成

我读到普通优先级的 Java 线程可能会得到 1 秒的时间片,所以我希望上面的线程 13 (t2) 对资源有交错访问,不一定一对一,但有些交错.

最佳答案

将您的 sleep 语句移到 synchronized block 之外,让其他线程有机会访问它。否则,您将依赖一个非常小的机会窗口让一个线程在释放监视器时访问该方法。

另一种方法是让您的 sleep 保持原样,但将持续时间从 1000 毫秒更改为 100 毫秒。然后将循环次数从 5 增加到 5000。

底线是线程资源竞争并不总是像人们预期的那样表现出来。线程并不总是合作以展示成功的交互。

class Resource {
private static Object monitor = new Object();

public static void access() {
synchronized (monitor) {
System.out.println(
String.format("Thread %d accessing resource",
Thread.currentThread().getId()));
System.out.println(
String.format("Thread %d leaving resource",
Thread.currentThread().getId()));
}
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
System.exit(1);
}
}

关于java - 为什么我的两个简单 Java 线程没有得到交错访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63749570/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com