`
chrhust
  • 浏览: 5657 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

多线程使用中的同步问题

阅读更多

这两天在学习多线程时遇到了一个奇怪的问题,贴上来供大家参考参考。
首先是一个简单的计数器。

 

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 多线程及线程同步 MFC 多线程及线程同步

    多线程临界段同步演示1

    本例中的"多线程不同步演示2"可能展示了没有同步机制时,多线程访问共享资源可能导致的问题,而"多线程临界段同步演示1"则可能是解决这个问题的示例。 临界区是Windows API提供的一种轻量级的同步工具,适合于在...

    3种多线程实现同步方法

    本篇文章将深入探讨三种在C++中实现多线程同步的方法:事件对象、关键代码段和互斥对象。 首先,我们来看**事件对象**。事件对象是一种信号机制,用于线程间通信和同步。在Windows API中,CreateEvent函数创建一个...

    MFC多线程同步类的使用

    【MFC多线程同步类的使用】 在MFC(Microsoft Foundation Classes)中,多线程编程是一项重要的技术,尤其在开发复杂的、并发执行的任务时。多线程允许程序同时执行多个任务,提升效率和响应速度。然而,线程间的...

    多线程同步解决卖票问题

    多线程同步解决卖票问题

    Java多线程同步.pdf

    Java 多线程同步中的两个特殊类 在Java语言中,有两个特殊的类用于多线程同步,分别是synchronized关键字和ReentrantLock类。 1. synchronized关键字 synchronized关键字是Java语言中的一种同步机制,用于对方法...

    使用三种VC的多线程同步方法编写一个多线程的程序

    1.使用三种VC的多线程同步方法编写一个多线程的程序(要求在屏幕上先显示Hello,再显示World)。 1)基于全局变量的多线程同步程序; 2)基于事件的多线程同步程序; 3)基于临界区的多线程同步程序。

    VC++多线程同步基本示例

    本示例着重讲解了VC++中的多线程同步,这是多线程编程中确保数据安全和正确性的重要概念。我们将深入探讨临界区、互斥量、事件和信号量这四种多线程同步机制。 1. **临界区(Critical Section)**:临界区是多线程...

    多线程数据同步

    "countErr"这个文件名可能是记录线程同步过程中错误计数的文件,这在调试多线程程序时非常有用,可以帮助开发者识别和修复同步问题。 总之,多线程数据同步是并发编程的关键挑战,通过使用临界区对象等同步机制,...

    Delphi多线程同步的例子

    本文将深入探讨Delphi中的多线程和线程同步,并以"SortThreads"和"delphi-thread-gui"这两个示例项目为例,讲解如何在实践中应用这些概念。 1. **多线程**:多线程允许应用程序同时执行多个独立的任务,提高程序的...

    多线程的同步机制 VC++

    多线程同步机制在软件开发中扮演着至关重要的角色,特别是在多处理器系统或者并发执行的任务中,确保线程间的正确协作和数据一致性是必不可少的。VC++中提供了多种同步机制来处理多线程间的同步问题,其中Event是...

    简单实现多线程同步示例(模拟购票系统)

    在编程领域,多线程是实现并发执行任务...总之,多线程同步是解决并发问题的关键,通过学习和实践这个简单的购票系统示例,开发者可以更好地理解和掌握Java中的线程同步机制,为解决实际项目中的并发问题打下坚实基础。

    多线程及线程同步

    然而,多线程环境下也带来了一些问题,尤其是资源竞争和数据一致性问题,这些问题需要通过线程同步机制来解决。本文将详细介绍如何通过临界区、互斥内核对象、事件内核对象和信号量内核对象来实现线程同步。 1. ...

    delphi中线程同步问题

    然而,在 DLL 或 ActiveForm(ActiveX Form)中使用 `Synchronize` 时,可能会遇到一些问题,导致程序出现死锁或者无法正常运行。本文将深入探讨 `Synchronize` 的工作原理,并提出解决 DLL/ActiveForm 中线程同步...

    多线程不同步读写共享资源代码

    满足这两个条件,就可以不用进行线程同步啦! 如何保证读在写之后呢,方法有多种,比如 读线程判断条件if(读指针 == 写指针)。写线程判断条件 if(下一个指针==读线程指针) 其实这就是一简单的生产者与消费者问题。 ...

    c# 多线程 同步问题解决

    lock 语句和 Monitor 类是解决 C# 中多线程同步问题的常用工具,它们通过确保线程之间有序地访问共享资源,防止数据不一致和其他线程同步问题的发生。在编写多线程程序时,开发者应深入理解多线程的原理和同步机制,...

    c++多线程同步——信号量

    在C++编程中,多线程同步是一种关键的技术,它允许多个执行线程协同工作,以避免数据竞争和死锁等并发问题。信号量(Semaphore)是实现多线程同步的一种有效工具,常用于控制对共享资源的访问。在这个名为"Mthread11...

    java多线程同步问题

    多线程注意:wait()方法的调用要有判定条件常用 while () obj.wait(timeout, nanos); ... // Perform action appropriate to condition } synchronized会影响共享数据,但对其他语句的执行不会有规律了!

Global site tag (gtag.js) - Google Analytics