这两天在学习多线程时遇到了一个奇怪的问题,贴上来供大家参考参考。
首先是一个简单的计数器。
package section_3;
public class Counter extends Thread{
static int count = 0;
synchronized public void incement(){
count++;
}
@Override
public void run(){
for(int i=0; i<10000; i++){
this.incement();
}
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
Counter t1 = new Counter();
Counter t2 = new Counter();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(count);
}
}
您可能会期望该程序最后会打印出20000,但是结果是非常让人失望的,synchronized似乎没有起到相应的作用,结果是不确定的。在我的机子上跑出来大概只有60%的概率会得出正确结果。这种同步失败的原因我还在研究。
下面来看一段正确的计数器代码:
package section_3;
public class AnotherCounter {
static class Counter{
int value = 0;
synchronized int getValue(){
return value;
}
synchronized void increment(){
value++;
}
}
/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
final Counter counter = new Counter();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0; i<10000; i++){
counter.increment();
}
}}, "t1");
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0; i<10000; i++){
counter.increment();
}
}}, "t2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(counter.getValue());
}
}
其不同之处主要在于取消了一个static变量,下面说说我的看法。
我们在使用synchronized关键字时,只能对对象(Object)进行锁定,那么在这里,首先,count是一个基本类型,不是一个Object,其次,它是一个static变量,是独立于具体实例对象的,即我们无法使用synchronized(this)来通过锁定实例对象来锁定它,因为它不是实例对象的成员变量。所以,解决办法是加入一个锁对象,通过它来对count进行加锁解锁,如下所示。
Object lock = new Object();
synchronized(lock){
//do something about count
}
这样就可以对static 基本类型进行同步了。
分享到:
相关推荐
d: 经典线程同步互斥问题 e: 使用关键段解决子线程互斥问题 f: 利用事件实现线程同步问题 g: 利用互斥量来解决线程同步互斥问题 h: problem1 生产者消费者问题 (1生产者 1消费者 1缓冲区) problem1 more ...
在Windows平台下,解决多线程同步互斥问题的一种常用方法是使用关键段(Critical Section)。关键段是一种轻量级的同步对象,用于保护共享资源免受并发访问的影响。一旦一个线程获得了对某个关键段的所有权,其他...
MFC 多线程及线程同步 MFC 多线程及线程同步 MFC 多线程及线程同步
本例中的"多线程不同步演示2"可能展示了没有同步机制时,多线程访问共享资源可能导致的问题,而"多线程临界段同步演示1"则可能是解决这个问题的示例。 临界区是Windows API提供的一种轻量级的同步工具,适合于在...
本篇文章将深入探讨三种在C++中实现多线程同步的方法:事件对象、关键代码段和互斥对象。 首先,我们来看**事件对象**。事件对象是一种信号机制,用于线程间通信和同步。在Windows API中,CreateEvent函数创建一个...
【MFC多线程同步类的使用】 在MFC(Microsoft Foundation Classes)中,多线程编程是一项重要的技术,尤其在开发复杂的、并发执行的任务时。多线程允许程序同时执行多个任务,提升效率和响应速度。然而,线程间的...
多线程同步解决卖票问题
Java 多线程同步中的两个特殊类 在Java语言中,有两个特殊的类用于多线程同步,分别是synchronized关键字和ReentrantLock类。 1. synchronized关键字 synchronized关键字是Java语言中的一种同步机制,用于对方法...
1.使用三种VC的多线程同步方法编写一个多线程的程序(要求在屏幕上先显示Hello,再显示World)。 1)基于全局变量的多线程同步程序; 2)基于事件的多线程同步程序; 3)基于临界区的多线程同步程序。
本示例着重讲解了VC++中的多线程同步,这是多线程编程中确保数据安全和正确性的重要概念。我们将深入探讨临界区、互斥量、事件和信号量这四种多线程同步机制。 1. **临界区(Critical Section)**:临界区是多线程...
"countErr"这个文件名可能是记录线程同步过程中错误计数的文件,这在调试多线程程序时非常有用,可以帮助开发者识别和修复同步问题。 总之,多线程数据同步是并发编程的关键挑战,通过使用临界区对象等同步机制,...
本文将深入探讨Delphi中的多线程和线程同步,并以"SortThreads"和"delphi-thread-gui"这两个示例项目为例,讲解如何在实践中应用这些概念。 1. **多线程**:多线程允许应用程序同时执行多个独立的任务,提高程序的...
多线程同步机制在软件开发中扮演着至关重要的角色,特别是在多处理器系统或者并发执行的任务中,确保线程间的正确协作和数据一致性是必不可少的。VC++中提供了多种同步机制来处理多线程间的同步问题,其中Event是...
在编程领域,多线程是实现并发执行任务...总之,多线程同步是解决并发问题的关键,通过学习和实践这个简单的购票系统示例,开发者可以更好地理解和掌握Java中的线程同步机制,为解决实际项目中的并发问题打下坚实基础。
然而,多线程环境下也带来了一些问题,尤其是资源竞争和数据一致性问题,这些问题需要通过线程同步机制来解决。本文将详细介绍如何通过临界区、互斥内核对象、事件内核对象和信号量内核对象来实现线程同步。 1. ...
然而,在 DLL 或 ActiveForm(ActiveX Form)中使用 `Synchronize` 时,可能会遇到一些问题,导致程序出现死锁或者无法正常运行。本文将深入探讨 `Synchronize` 的工作原理,并提出解决 DLL/ActiveForm 中线程同步...
满足这两个条件,就可以不用进行线程同步啦! 如何保证读在写之后呢,方法有多种,比如 读线程判断条件if(读指针 == 写指针)。写线程判断条件 if(下一个指针==读线程指针) 其实这就是一简单的生产者与消费者问题。 ...
lock 语句和 Monitor 类是解决 C# 中多线程同步问题的常用工具,它们通过确保线程之间有序地访问共享资源,防止数据不一致和其他线程同步问题的发生。在编写多线程程序时,开发者应深入理解多线程的原理和同步机制,...
在C++编程中,多线程同步是一种关键的技术,它允许多个执行线程协同工作,以避免数据竞争和死锁等并发问题。信号量(Semaphore)是实现多线程同步的一种有效工具,常用于控制对共享资源的访问。在这个名为"Mthread11...
多线程注意:wait()方法的调用要有判定条件常用 while () obj.wait(timeout, nanos); ... // Perform action appropriate to condition } synchronized会影响共享数据,但对其他语句的执行不会有规律了!