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

使多个线程使用并更改同一个变量

宇文和同
2023-03-14

在我的程序中,我需要多个线程使用和编辑同一个变量,但它似乎不起作用。这是我的意思的一个例子,这将是我的主要课程。

public class MainClass {

  public static int number = 0;
  public static String num = Integer.toString(number);

  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    System.out.println("Enter number of threads.");
    int threads = in.nextInt();
    for (int n = 1; n <= threads; n++) {
      java.lang.Thread t = new Thread();
      t.start();
    }
  }
}

这将是我的Thread类:

public class Thread extends java.lang.Thread
{
  public void run()
  {
      MainClass.number++;
      System.out.println("Thread started");
      System.out.println(MainClass.num);
  }
}

我当场编写了这段代码,所以可能会有一些错误,但没关系。我的程序基本上需要这样做,但不是每次打印数字加1,而是所有线程只需多次打印相同的数字0。请帮帮我,谢谢。

共有2个答案

逄岳
2023-03-14

在这里你去...

 import java.util.Scanner;
    import java.util.concurrent.atomic.AtomicInteger;

    public class UpdateVariables
    {
        static int num = 0;
        public static AtomicInteger  atomicInteger = new AtomicInteger(num);


        @SuppressWarnings("resource")
        public static void main(String args[])
        {
            Scanner userInput = new Scanner(System.in);
            System.out.println("Enter Number of Threads: ");
            int getThreadNumber = userInput.nextInt();
            for(int i = 0; i < getThreadNumber; i++)
            {
                PrintThread p = new PrintThread();
                p.start();
            }

        }

    }

    class PrintThread extends Thread
    {
        public void run()
        {
            System.out.println("Thread Started: ");
            System.out.println(UpdateVariables.atomicInteger.incrementAndGet());

        }
    }
江飞白
2023-03-14

在我的程序中,我需要多个线程使用和编辑同一个变量,但它似乎不起作用。。。

每当多个线程更新同一变量时,都需要担心内存同步问题。线程获得高性能的一种方法是,每个线程都使用本地CPU内存缓存,因此可能使用变量的陈旧副本。您需要使用synchronized或volatile关键字强制线程的缓存将任何更新写入中央存储或从中央更新其缓存。

尽管这会处理内存同步,但它并不一定会保护您免受竞争条件的影响。同样重要的是要意识到实际上是3个操作:获取当前值、递增它并再次存储它。如果多个线程试图这样做,则存在线程竞争条件可能会导致操作被遗漏。

在这种情况下,应该使用AtomicInteger类,该类封装了volatile int字段。它提供了像incrementAndGet()这样的方法,这些方法以线程安全的方式递增该字段。

public static AtomicInteger number = new AtomicInteger(0);
...
MainClass.number.incrementAndGet();

然后,多个线程可以安全地递增同一变量。

 类似资料:
  • 我有一个疑问相对于UI线程和其他线程之间的concurrency。 Ui主线程更新不同变量的值:-flol-long-boolean 我还有另一个线程,它读取同一个变量,并用它执行一些逻辑操作(不编辑它的值),然后用这个操作的结果发送本地广播消息。 是否存在并发问题???我必须使用同步方法和原子变量,否则就无关紧要了? 我反思这个问题,因为没有浮点基元的原子变量,也因为我害怕用错误的代码阻止Ui线

  • 我有多个线程,它们都从一个对象运行。我希望“主线程”单独运行,直到某一点,然后它等待,所有其他线程一起运行,然后主线程唤醒,等等。。。。。我无法同步线程。我要么得到一个非法的监视器状态异常,要么它卡在一个“等待”循环中,该循环应该接收一个永远不会到达的“通知”。 更具体地说,我有一个带有数组的对象。阵列中的每个单元都有一个线程,该线程检查相邻单元,然后使用该信息更改其单元。为了有序地进行更改,我希

  • 问题内容: 我有一个使用Redis发布/订阅在Java中使用Jedis客户端在客户端之间传输消息的应用程序。我希望能够在用户键入命令时在运行时订阅频道,但是由于订阅是一个阻塞操作,因为它在调用订阅的线程上进行侦听,所以我不确定以后如何订阅其他频道在原始线程上。 例: 这将起作用,除了调度命令的线程将用于轮询Redis,而我将无法使用该线程订阅更多的频道。 问题答案: 我观察到了同样的问题,即订阅后

  • 面试问题 比如说,我们有一个在Employee表中有200万条记录的表,我们需要削减每个员工10%的工资(需要做一些处理),然后将其保存回collection。你怎样才能有效地做到这一点。 我问他,我们可以使用executor框架来创建多个线程,这些线程可以从表中获取值,然后我们可以处理并将其保存到列表中。 然后他问我,你将如何检查一个记录是否已经被处理,我不知道(如何做)。 甚至我也不确定我是否

  • 问题内容: 线程都是可运行的,并且它们拥有相同的锁。两个线程都可以运行时,它们可以锁定相同的地址吗?那是JRE错误吗? 问题答案: 该问题仅存在于线程转储中。实际上,在任何时间点,锁都仅由一个线程持有。但是,线程转储显示两个具有相同锁的不同线程,因为它不是原子的。 可以使用以下程序轻松重现该行为:

  • 我正在使用最新的Java8 lambdas和并行流处理数据。我的代码如下: 流以一个元素开始,但在第二阶段会添加更多的元素。我的假设是这个流应该并行运行,但在这种情况下只使用一个工作线程。 如果我从2个元素开始(即我在初始列表中添加第二个元素),那么就会产生2个线程来处理流,依此类推...如果我没有显式地将流提交给ForkJoinPool,也会发生这种情况。 问题是:它是记录在案的行为还是可能在实