多线程访问内部类
我创建了3个正在访问ThreadsAroundInnerClasses
外部类的内部类MyInnerClass
的ThreadsAroundInnerClasses
。
package com.test; public class ThreadsAroundInnerClasses { public static void main(String[] args) { Thread t1 = new Thread(new MyThread(), "THREAD-1"); Thread t2 = new Thread(new MyThread(), "THREAD-2"); Thread t3 = new Thread(new MyThread(), "THREAD-3"); t1.start(); t2.start(); t3.start(); } static class MyInnerClass { static int counter = 0; public void printIt(String threadName) { System.out.println("I am inside inner class, counter value is " + ++counter + " and thread name is " + threadName); } } } class MyThread implements Runnable { @Override public void run() { ThreadsAroundInnerClasses.MyInnerClass innerObj = new ThreadsAroundInnerClasses.MyInnerClass(); innerObj.printIt(Thread.currentThread().getName()); } }
在输出中,我可以看到MyInnerClass
类中的counter
静态变量没有按顺序更新。
I am inside inner class, counter value is 1 and thread name is THREAD-1 I am inside inner class, counter value is 3 and thread name is THREAD-2 I am inside inner class, counter value is 2 and thread name is THREAD-3
如果有人能解释如何在多线程的情况下处理内部类,那将会非常有帮助。 我们可以同步整个内部课堂吗?
先谢谢您的帮助。
班级是不是内部班级是无关紧要的。 你在这里看到的是预期的输出:你的程序中没有任何同步,并且线程调度程序因此可以随意切换到其他线程。 这里有一系列可能的操作,这会导致你看到的输出。
如果你想要计数器增量,连接和打印是一个原子操作,那么你应该确保它在一个唯一的锁上同步:
synchronized MyInnerClass.class {
System.out.println("I am inside inner class, counter value is " + ++counter + " and thread name is " + threadName);
}
尝试这个:
static class MyInnerClass {
static int counter = 0;
public void printIt(String threadName) {
synchronized(MyInnerClass.class) {
System.out.println("I am inside inner class, counter value is " + ++counter + " and thread name is " + threadName);
}
}
}
你的计数器是静态的,所以你需要在整个类对象上进行同步。
这是一个阅读 - 然后改变和线程可见性的问题
读那么变化
增量首先是读取,然后是添加,然后是回写。 ++counter
是counter = counter + 1
简写,这意味着:“读取计数器,添加一个,将结果写回计数器”。 这个流程可以在另一个线程的中间被中断:Thread1读取计数器,得到1 - 并被中断。 线程2读取计数器 - 它仍然是1 - 增加1 - 并被中断。 线程3读取计数器 - 它仍然是1 - ....等等。 行为基本上是随机的。 只需在后台运行其他应用程序,您可能会激发不同的输出。
线程可见性
对于多核架构中的非易失性非同步变量,不同的线程可能在不同的内核上运行,并且内核可能会在其寄存器上缓存该变量。 这意味着一个线程可能无法看到另一个线程写入该变量 - 直到它被提交回内存并且有新的写入。
同步是创造记忆障碍的一种方式。 系统将保证下次进行锁定时,写入锁内的所有内容均可见。 实际上 - 当你退出同步块时,你所做的每件事都被记录下来。 然后你进入同步块,所有内容都从内存中读回来。
volatile
关键字告诉系统禁止将变量缓存在寄存器中 - 它必须始终在内存中读写。 这使得每个人都阅读到最新的内容,但由于上述原因,这并不能解决您的问题。
简单的解决方案
解决您的特定问题的最简单方法是使用AtomicInteger。
static class MyInnerClass {
static final AtomicInteger counter = new AtomicInteger(0);
public void printIt(String threadName) {
System.out.println("I am inside inner class, counter value is " +
counter.incrementAndGet() + " and thread name is " + threadName);
}
}
这将为您节省所有同步的麻烦 - 它包含在AtomicInteger类中。
链接地址: http://www.djcxy.com/p/92057.html