当前位置: 首页 > 知识库问答 >
问题:

即使同步块中有其他线程更新,线程也无法获取最新值?

章涵容
2023-03-14

我编写这个程序是为了模拟字段可见性

package com.example.threads.fieldvisibility.main;

public class ThreadVisibilityWithSyncKeyWord implements Runnable {

    private boolean stop = false;

    @Override
    public void run() {
        while (!stop) {

            // System.out.println("stop is " + stop);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadVisibilityWithSyncKeyWord test = new ThreadVisibilityWithSyncKeyWord();
        Thread t = new Thread(test);
        System.out.println("Starting Thread");
        t.start();
        Thread.sleep(5000);
        System.out.println("Stopping Thread");

        synchronized (test) {
            test.stop = true;
        }
        t.join(5000);
        System.out.println("Thread State: " + t.getState());
    }
}

程序很简单。我们有两个线程。主线程确实使用“test”对象同步块中将标志“Stop”更改为true。

我预计一旦主线程将此设置为true,就会使while循环终止。但是,即使主线程将标志设为true,另一个线程也看不到最新的值(即使它是在同步块中更新的)。

奇怪的是,当我取消注释系统.out.println()(在里面)时,线程确实“看到”了最新的值并终止了。

我不明白这种行为。为什么其他线程无法看到在主线程的同步块中更新的最新值。在取消注释 sysout 之后,是什么原因导致另一个线程看到该标志的最新值?

共有2个答案

寿伟
2023-03-14

我认为主要的问题是项目是如何构建的,如果你把主线程类从你的runnable中分离出来,一切都会变得更容易。

这是一个工作示例,结果如下:(注意,我在线程中增加了1秒钟的睡眠时间,以避免多次打印输出)

>

  • 启动线程
  • 停止为假
  • 停止为假
  • 停止为假
  • 停止为假
  • 停止线程
  • 停是真的
  • 线程状态:已终止

    包装网项目;

    公共类Main{

    public static boolean stop = false; 
    
    public static void main(String[] args) throws InterruptedException {
        ThreadVisibilityWithSyncKeyWord test = new ThreadVisibilityWithSyncKeyWord();
        Thread t = new Thread(test);  
        System.out.println("Starting Thread");
        t.start();
        Thread.sleep(5000);
        System.out.println("Stopping Thread");
    
        stop = true;
    
        t.join(5000);
        System.out.println("Thread State: " + t.getState());
    
    }
    

    }

    包装网项目;

    公共类ThreadVisibilityWithSyncKeyWord实现Runnable {

    @Override
    public void run() {
        while (!Main.stop) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
            System.out.println("stop is " + Main.stop);
        }
    }
    

    }

  • 暨曾笑
    2023-03-14

    当线程进入< code>synchronized块时,通过从共享缓存/内存中读取数据,可以保证看到被访问变量的当前状态。在< code>synchronized块中写入变量将保证变量被写入共享缓存/内存。

    发生了什么:

    • 测试已创建
    • main-线程缓存测试。停止
    • 测试缓存stopfalse
    • 测试开始
    • test从本地缓存中读取值
    • main-线程集测试。停止true
    • 因为这是同步的,所以也会写入共享缓存
    • test继续从自己的缓存中读取停止

    当您将打印行添加到代码中时,您必须知道System.out。println涉及内部同步:

    • main-线程将test.stop设置为true
    • 因为这是同步完成的,所以也会写入共享缓存
    • test执行println,此时内部同步导致test从共享缓存中读取新值

     类似资料:
    • 我正在编写一个Android应用程序,它连接到蓝牙设备,读取设备发送的数据,将其添加到AChartEngine图形中,并在文本视图中显示数据。 我的Bluetooth代码与BluetoothChat示例代码中的线程实现非常相似(它与SDK一起提供)。我可以在LogCat中看到< code>ConnectedThread循环正在执行并因此获得新数据,但我的TextView在7行之后停止更新,图形间歇

    • 方法有一个有趣的属性,它将允许其他线程在被阻止时进入其同步块。例如(假设线程1首先运行): 线程1: 线程2: 线程 2 能够唤醒线程 1 的事实意味着线程 2 进入了同步块,即使其他某个线程位于同一对象的同步块中也是如此。这对我来说很好,但我想知道这是否只发生在或所有会使线程“等待”的方法()上。在我的情况下,我关心,因为如果行为与相同,它会破坏我的代码: 那么,多个线程是否可能因为join调用

    • 问题内容: 如果我在同步块内创建一个新线程,该块是否将保持锁定状态,直到线程执行完成为止?如果没有,那么直到什么时候才能保持锁定状态? 问题答案: 如果代码d具有新创建的线程,则它将保持锁定,从而等待它完成。由于没有锁,因此在调用完成后将不释放锁定。

    • 我尝试使用ArrayList解决生产者和消费者问题(我知道ArrayList是nt threadsafe),我确保使用关键字放置列表,但仍然进入。这就是错误 启动生产者请提供作业详细信息:TestJob作业完成:TestJob Exception位于java.util.ArrayList$itr.checkforcoModification(未知源)位于test.thread.consumer.r

    • 问题内容: 在Linux中,可以使用backtrace()库调用来获取回溯,但是它仅返回当前线程的回溯。假设我知道它是TID(或pthread_t)并且可以保证它可以入睡,是否有任何方法可以获取其他线程的回溯? 看来libunwind(http://www.nongnu.org/libunwind/)项目可以提供帮助。问题是CentOS不支持它,因此我不希望使用它。 还有其他想法吗?谢谢。 问题答

    • 所以我有一个任务来创建一个程序,它有一个起始余额为1的银行账户。然后,我创建了一组卡,可以访问该帐户、存款或取款,但不能同时进行。我创建了许多线程,然后使用这些线程访问银行帐户,提取或存入随机金额,然后退出。 我的卡片类别: 我的帐户类别: } 我的课程 } 输出示例: http://puu.sh/lvoE5/05ebcd4c74.png 正如你所看到的,它对每一张不同的卡都有效,它回到5000,