1

I have a problem where i have to print the numbers in such format.

First  1
First  2
Second  3
Second  4
First  5
First  6
Second  7
Second  8
First  9
and so on...

I have implemented my runnable interface as below.

class ThreadDemo implements Runnable {

 public volatile Integer num;

 public Object lock;

 public ThreadDemo(Integer num, Object lock) {
  this.num = num;
  this.lock = lock;
 }

 @Override
 public void run() {

  try {
   while (true) {
    int count = 0;
    synchronized(lock) {
     Thread.sleep(100);
     while (count < 2) {
      System.out.println(Thread.currentThread().getName() + "  " + num++);
      count++;

     }
     lock.notify();
     lock.wait();
    }
   }
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
 }
}

My main class is as follows

public class CoWorkingThreads {
 private static volatile Integer num = new Integer(1);
 public static void main(String...args) {
  Object lock = new Object();
  Thread thread1 = new Thread(new ThreadDemo(num, lock), "First");
  thread1.start();
  Thread thread2 = new Thread(new ThreadDemo(num, lock), "Second");
  thread2.start();

 }
}

when i run the program i am getting the output as follows

First  1
First  2
Second  1
Second  2
First  3
First  4
Second  3
Second  4

Instead of previously expected results. But when I Change the integer to atomic integer type i start getting the expected result. can anyone explain what is i can do to make it run with integer instead of using atomic integer

4

4 回答 4

1

Java Integer 不能通过引用传递。在您的代码中,每个线程都会创建变量的副本。但是 atomicInteger 可以通过引用传递。

此外,为了获得正确的结果,您可以将 num 变量更改为静态变量。

public static Integer num = 1;

public Object lock;
public ThreadDemo(Integer num, Object lock) {
    //this.num = num;
    this.lock =lock;
}
于 2019-02-18T18:59:54.967 回答
0

您的问题是 Integer 类是Immutable,因此您不能在单独的线程中使用它来引用共享值。答案:创建您自己的 Mutable Integer 类。

您可以在这里找到关于 SO 回答的类似问题

于 2019-02-18T18:58:19.110 回答
0

仅就您的知识而言,您可能希望尝试使用(s) (例如) 及其相关联的 (s),而不是在 上使用synchronized块。ObjectLockReentrantLockCondition

使用Condition(s) 您可以在线程之间以互斥的方式管理共享资源。

于 2019-02-18T19:12:56.543 回答
-2

我仍然认为这个问题没有得到正确回答。这里的缺陷是您从未将共享数据标记为static. 所以每个线程都有自己独立的副本。Integer是一个不可变的包装类,这是真的,但在这种情况下它没有任何关系。让我们深入研究一下num++。该++运算符仅适用于(原始)整数类型。在幕后,num拆箱,++应用,然后将结果分配回num(在装箱转换之后)。该类Integer没有++运算符。事实上,Integer对象是不可变的。

不可变意味着每次你增加并创建一个新的值对象。并且该新值对象被分配回您的num引用。但是两个线程有​​自己的num引用副本,指向不同的Integer盒装原语。因此,它们彼此独立地增加它,而彼此不可见。如果你想在线程之间共享它,你必须static在声明的地方使用访问修饰符。将两个值传递给共享变量是没有意义的。相反,您可以内联初始化它。这是固定版本。

public class ThreadDemo implements Runnable {
    public static Integer num = 1;

    public static final Object lock = new Object();

    public ThreadDemo() {
    }

    @Override
    public void run() {

        try {
            while (true) {
                int count = 0;
                synchronized (lock) {
                    Thread.sleep(100);
                    while (count < 2) {
                        System.out.println(Thread.currentThread().getName() + "  " + num++);
                        count++;

                    }
                    lock.notify();
                    lock.wait();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class CoWorkingThreads {
    public static void main(String[] args) {
        Thread thread1 = new Thread(new ThreadDemo(), "First");
        thread1.start();
        Thread thread2 = new Thread(new ThreadDemo(), "Second");
        thread2.start();
    }
}

最后使用客户端提供的锁对象违反了同步策略的封装。所以我改用了内部私有锁对象。

这是新的输出。

第一 1 第一 2 第二 3 第二 4 第一 5 第一 6 第二 7 第二 8 第一 9 第一 10

于 2019-02-19T03:43:10.047 回答