代码如下:
package com.bohai.thread; public class ThreadNoSynchronized { public static void main(String[] args) { ShareData oShare = new ShareData(); // 创建,初始化ShareData对象oShare ThreadDemo th1 = new ThreadDemo("Thread1", oShare); // 创建线程th1 ThreadDemo th2 = new ThreadDemo("Thread2", oShare); // 创建线程th2 th1.start(); // 启动线程th1 th2.start(); // 启动线程th2 } } class ShareData { public static String szData = ""; // 声明,并初始化字符串数据域,作为共享数据 } class ThreadDemo extends Thread { private ShareData oShare; // 声明,并初始化ShareData 数据域 ThreadDemo() { } // 声明,并实现ThreadDemo 构造方法 // 声明,并实现ThreadDemo 带参数的构造方法 ThreadDemo(String szName, ShareData oShare) { super(szName); // 调用父类的构造方法 this.oShare = oShare; // 初始化oShare域 } public void run() { for (int i = 0; i < 10; i++) { if (this.getName().equals("Thread1")) { oShare.szData = "这是第 1 个线程"; // 为了演示产生的问题,这里设置一次睡眠 try { Thread.sleep((int) Math.random() * 100); // 休眠 } catch (InterruptedException e) { // 捕获异常 } System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息 } else if (this.getName().equals("Thread2")) { oShare.szData = "这是第 2 个线程"; // 为了演示产生的问题,这里设置一次睡眠 try { Thread.sleep((int) Math.random() * 100); // 线程休眠 } catch (InterruptedException e) // 捕获异常 { } System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息 } } } }
执行结果如下:
Thread1:这是第 2 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread1:这是第 1 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
Thread2:这是第 2 个线程
从结果可以看出,这不是我们期望的结果:优化后代码如下:
package com.bohai.thread; public class ThreadNoSynchronized { public static void main(String[] args) { ShareData oShare = new ShareData(); // 创建,初始化ShareData对象oShare ThreadDemo th1 = new ThreadDemo("Thread1", oShare); // 创建线程th1 ThreadDemo th2 = new ThreadDemo("Thread2", oShare); // 创建线程th2 th1.start(); // 启动线程th1 th2.start(); // 启动线程th2 } } class ShareData { public static String szData = ""; // 声明,并初始化字符串数据域,作为共享数据 } class ThreadDemo extends Thread { private ShareData oShare; // 声明,并初始化ShareData 数据域 ThreadDemo() { } // 声明,并实现ThreadDemo 构造方法 // 声明,并实现ThreadDemo 带参数的构造方法 ThreadDemo(String szName, ShareData oShare) { super(szName); // 调用父类的构造方法 this.oShare = oShare; // 初始化oShare域 } public void run() { for (int i = 0; i < 10; i++) { if (this.getName().equals("Thread1")) { synchronized (oShare) { oShare.szData = "这是第 1 个线程"; } // 为了演示产生的问题,这里设置一次睡眠 try { Thread.sleep((int) Math.random() * 100); // 休眠 } catch (InterruptedException e) { // 捕获异常 } System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息 } else if (this.getName().equals("Thread2")) { synchronized (oShare) { oShare.szData = "这是第 2 个线程"; } // 为了演示产生的问题,这里设置一次睡眠 try { Thread.sleep((int) Math.random() * 100); // 线程休眠 } catch (InterruptedException e) // 捕获异常 { } System.out.println(this.getName() + ":" + oShare.szData); // 输出字符串信息 } } } }
对共享变量需要进行同步。不要在方法上使用 synchronized。
相关推荐
"某电信项目多线程同步数据实例"的标题揭示了一个具体的应用案例,它表明在该电信项目中,开发团队使用了多线程技术来高效地同步和处理数据。描述中提到的“经生产测试,一分钟同步数据量20W”,这展示了该技术方案...
2. 线程同步: 当多个线程访问共享资源时,可能会出现竞态条件。C#提供了多种同步机制来防止这种情况: - `Mutex`:互斥量,一次只允许一个线程访问资源。 - `Semaphore`:信号量,限制同时访问资源的线程数量。 ...
这个"17_懒汉式多线程同步优化.zip"文件很可能包含了一个关于如何在C++中实现这一策略的详细教程,特别是针对多线程环境下的性能优化。 在多线程环境中,当多个线程试图访问同一资源时,如果没有正确的同步机制,...
本实例将深入探讨如何在LabWindows/CVI中有效地使用线程锁和线程安全变量来实现多线程程序设计。 首先,我们来看线程锁。线程锁,也称为互斥锁,是一种同步机制,用于确保同一时间只有一个线程可以访问特定的资源或...
了解并掌握如何创建线程、控制线程同步、处理线程异常以及优化线程使用,对于任何Java程序员来说都是至关重要的。通过阅读提供的“多线程的入门 实例源码”,你可以更加直观地学习这些概念,并在实践中提升自己的多...
总之,这个.NET 2.0的多线程实例涵盖了多线程的创建与管理、线程同步、UI更新、文件系统操作、异步编程等多个核心知识点,对于理解和实践.NET环境下的并发编程具有很高的价值。通过学习和实践这些示例,开发者可以...
本资源提供的是五个关于VC++多线程和进程编程的实例,旨在帮助开发者深入理解这两个概念以及线程同步控制量的使用。 首先,我们来探讨多线程编程。在单线程程序中,所有任务都按顺序执行,而多线程程序则可以同时...
压缩包内的“多线程实例”很可能是实际代码示例,包括上述概念的实际应用,如创建和管理线程、线程同步和通信的实例代码,以及可能的性能测试和调试工具的使用。 通过学习这些实例,开发者可以更深入地理解vc中的多...
本文将深入探讨C#中的线程同步机制,并结合实例进行讲解。 1. **线程与多线程** 线程是程序执行的基本单元,每个线程都有自己的执行路径。在单核处理器系统中,线程的切换由操作系统调度完成;而在多核处理器系统...
3. **线程同步实例** 例如,我们可以使用`Mutex`来实现线程间的互斥访问。在多线程实例中,可能有如下代码: ```csharp Mutex mutex = new Mutex(); void MyThreadMethod() { mutex.WaitOne(); // 获取锁 //...
在多线程环境中,线程同步至关重要,以避免数据竞争和死锁等问题。VC++提供了多种同步机制,如Critical Section(临界区)、Mutex、Semaphore和Event。例如,Critical Section用于保护对共享资源的访问,确保同一...
6. **线程同步**:在多线程环境中,数据共享可能会引发竞态条件和死锁问题。MFC提供了一些同步机制,如`CSemaphore`, `CCriticalSection`, `CMutex`等,用于控制对共享资源的访问。 7. **线程通信**:`PostMessage`...
在计算机科学中,进程线程通信、线程同步与异步以及进程间的通信是操作系统核心概念,对于理解和优化多任务并行处理至关重要。这些概念在软件开发,尤其是并发编程领域中占据着举足轻重的地位。 首先,让我们来探讨...
总结起来,这个压缩包提供了一系列的C#多线程编程实例,涵盖了从基础的线程创建到高级的线程同步、异步操作、应用域、委托和线程池等多个方面。通过学习和实践这些例子,开发者可以更好地理解和掌握C#中的多线程编程...
QT框架中的多线程同步是实现高效并发编程的关键技术,其中`QSemaphore`是一个重要的工具。`QSemaphore`是Qt的并发类库中的一员,它主要用于控制对共享资源的访问,实现线程间的同步和互斥。理解并熟练运用`...
2. 线程同步:通过互斥量确保对共享资源的独占访问。 ```c #include #include pthread_mutex_t mutex; int shared_resource = 0; void* increment(void* arg) { for (int i = 0; i ; ++i) { pthread_mutex_...
3. 线程同步:为了防止数据竞争和死锁,我们需要使用各种同步机制,如Mutex(互斥量)、Semaphore(信号量)、Critical Section(临界区)和Event(事件)等。 三、线程通信 1. 同步原语:Windows API提供了多种...
事件是另一种线程同步机制,它可以用来通知线程何时开始执行或停止。事件有两种状态:有信号状态和无信号状态。线程可以等待事件,直到事件被设置为有信号状态。在Windows API中,可以使用`CreateEvent`创建事件,`...
另一个用于线程同步的工具是"信号量"。信号量是一种计数器,可以限制同时访问某个资源的线程数量。在Java中,可以使用`Semaphore`类实现信号量,它提供了获取和释放许可证的方法,防止过多线程同时访问有限资源,...