我对多线程有一个想法,但我从未参与其中。所以,当我在工作中看到我的应用程序时...我还没有看到任何类扩展Thread创建Thread
。因此,当2个对象同时尝试访问变量时,使用synchronized
关键字。我们使用synchronized来避免冲突。
示例:
public class Test {
private static int count = 0;
public static synchronized void incrementCount() {
count++;
}
}
如果测试类是由对象使用的话,那么将synchronized
添加到incrementcount()
是有意义的。但是,如果您不延长Thread
或Runnable
那么使用synchronized
编写的内容。
答案 0 :(得分:2)
同步不适用于线程或Runnables,它用于多个线程访问的数据结构,以确保每个线程以不会破坏其数据的方式访问它们。你自己的例子是一个基本的例子,其中count以一种不是线程安全的方式递增(using ++, see this question),所以它需要锁定以确保一次只有一个线程可以递增它。 / p>
如果有其他访问计数的代码,则还需要进行同步,以便可以看到对计数的更新。如果你所做的只是增加一个计数器,那么使用像java.util.concurrent.atomic.AtomicInteger
这样的类更有意义,你可以完全没有synchronized关键字。
对于使用synchronized来理解它确实假设有多个线程。即使您自己的代码没有创建新线程,也可能存在多个线程正在调用您的代码的情况(例如在servlet容器中,容器管理线程池并为每个传入请求分配线程)。
答案 1 :(得分:1)
一个类不需要extend Thread
或implements Runnable
将其标记的方法标记为已同步以防止多线程访问
您的类可能是某个其他线程类的参数,并且该线程类可能有多个实例。为了提供强大的数据一致性,您可以保护代码的关键部分。数据。
只需更改您的代码示例,如下所示。
我正在展示" synchronized
"在对象级别而不是类级别(static synchronized
)
class Test {
private int count = 0;
public void incrementCount() {
count++;
System.out.println("Count:"+count);
}
}
class MyRunnable implements Runnable{
private Test test = null;
public MyRunnable(Test t){
this.test = t;
}
public void run(){
test.incrementCount();
}
}
public class SynchronizedDemo{
public static void main(String args[]){
Test t = new Test();
for ( int i=0; i<10; i++){
new Thread(new MyRunnable(t)).start();
}
}
}
您的班级Test
已作为参数传递给帖子MyRunnable
。现在您已经创建了多个线程实例。如果没有synchronized
关键字,则输出无法预测,如下所示。
java SynchronizedDemo
Count:2
Count:3
Count:2
Count:7
Count:6
Count:5
Count:4
Count:10
Count:9
Count:8
如果我改变
public void incrementCount() {
到
public synchronized void incrementCount() {
输出是:
Count:1
Count:2
Count:3
Count:4
Count:5
Count:6
Count:7
Count:8
Count:9
Count:10
另外,您已将方法设为static synchronized
。 That means lock is maintained at class level instead of object level.
查看oracle文档page以便更好地理解。
缺少&#34; static synchronized
&#34;
class Test {
private static int count = 0;
public static void incrementCount() {
count++;
System.out.println("Count:"+count);
}
}
class MyRunnable implements Runnable{
private Test test = null;
public MyRunnable(Test t){
this.test = t;
}
public void run(){
test.incrementCount();
}
}
public class SynchronizedDemo{
public static void main(String args[]){
for ( int i=0; i<10; i++){
Test t = new Test();
new Thread(new MyRunnable(t)).start();
}
}
}
输出:
Count:5
Count:4
Count:3
Count:2
Count:10
Count:9
Count:8
Count:7
Count:6
制作后
public static void incrementCount() {
到
ppublic static synchronized void incrementCount() {
输出:
Count:1
Count:2
Count:3
Count:4
Count:5
Count:6
Count:7
Count:8
Count:9
Count:10
在此示例中,与之前不同,我们创建了10个不同的Test
个实例。
答案 2 :(得分:0)
i++
,即使它看起来像一条指令,实际上也是多条指令:
1+i
。i
设置为临时变量。但是,假设执行i++
的线程在步骤1
之后被中断,并且中断线程也调用i++
。然后,这会发生:
(假设i=1
)
1+i
或2
。 i+1
,同时2
i
设置为临时变量2。现在i=2
i
设置为临时变量1。现在i=2
问题是,如果i++
被调用两次,则应为3
,而不是2
。
synchronized void
会锁定变量i
,直到整个void
完成执行。例如:
1+i
或2
。锁定变量i
。i+1
,但由于锁定变量i
i
设置为临时变量1。现在i=2
。变量i
现已解锁。i
已解锁,因此它将临时变量2设置为i+1
3
。i
设置为3
,这是预期的行为。 synchronized void
本质上是暂时锁定变量,以避免混淆程序的执行。