package ThreadTest;
public class ThreadTest {
public static void main(String args[]){
MyThread mt = new MyThread() ; // 定义线程对象
Thread t1 = new Thread(mt) ; // 定义Thread对象
Thread t2 = new Thread(mt) ; // 定义Thread对象
Thread t3 = new Thread(mt) ; // 定义Thread对象
t1.start() ;
t2.start() ;
t3.start() ;
}
}
class MyThread implements Runnable{
private int ticket = 5 ; // 假设一共有5张票
public void run(){
// synchronized (this){
while(ticket>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("卖票:ticket = " + ticket-- );
}
// }
}
}
线程不安全条件
1 mt为一个对象实例
2 存在多个线程同时修改一个对象实例的属性,每个线程都有自己的临时空间用来保存对象实例的值,所以该值在被修改后不会马上同步到对象中,造成别的线程读到的不是对象实例最新的值,从而导致数据脏读,再造成脏写
运行结果如下
卖票:ticket = 5
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 3
卖票:ticket = 1
卖票:ticket = 0
卖票:ticket = -1
修改: 同步代码块,使一个时间里,只有一个线程可以访问该代码。从而保证数据的修改是单线程同步的
class MyThread implements Runnable{
private int ticket = 5 ; // 假设一共有5张票
public void run(){
synchronized (this){
while(ticket>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("卖票:ticket = " + ticket-- );
}
}
}
}
卖票:ticket = 5
卖票:ticket = 4
卖票:ticket = 3
卖票:ticket = 2
卖票:ticket = 1
synchronized (this){
}
同步的是一个属性,而不是代码段(而this 代表了本类,即此时本类中的别的方法也被同步?)
改进 用byte[] lock = {0}; 代替this. 比较省内存
class MyThread implements Runnable{
private int ticket = 5 ; // 假设一共有5张票
private byte[] lock = {0};
public void run(){
synchronized (lock){
while(ticket>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("卖票:ticket = " + ticket-- );
}
}
}
}
或者直接synchronized 多线程访问修改的属性 synchronized的是数组
class MyThread implements Runnable{
private int[] ticket = {5} ; // 假设一共有5张票
public void run(){
synchronized(ticket){
sale();
}
}
private void sale(){
while(ticket[0]>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("卖票:ticket = " + ticket[0]-- );
}
}
}
2 同步方法
class MyThread implements Runnable{
private int ticket = 5 ; // 假设一共有5张票
public void run(){
sale();
}
private synchronized void sale(){
while(ticket>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("卖票:ticket = " + ticket-- );
}
}
}
以下为线程安全的,但是继承Thread类后,资源(ticket )没有共享,各自卖各自的票。而实现runnable接口是可以资源共享的
package ThreadTest;
public class ThreadTestFirst {
public static void main(String args[]){
MyThreadF a = new MyThreadF("a");
MyThreadF b = new MyThreadF("b");
a.start();
b.start();
}
}
class MyThreadF extends Thread{
private int ticket = 5 ; // 假设一共有5张票
private String name;
public MyThreadF(String name) {
this.name = name;
}
public void run(){
while(ticket>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(this.name + "卖票:ticket = " + ticket-- );
}
}
}
a卖票:ticket = 5
b卖票:ticket = 5
b卖票:ticket = 4
a卖票:ticket = 4
b卖票:ticket = 3
a卖票:ticket = 3
b卖票:ticket = 2
a卖票:ticket = 2
a卖票:ticket = 1
b卖票:ticket = 1
分享到:
相关推荐
HashMap线程不安全的原因主要在于以下几个方面: 1. 多线程环境下并发修改:在多线程环境下,如果多个线程同时对HashMap进行读写操作,可能会导致数据的不一致性和数据丢失。例如,当一个线程正在执行put操作时,另...
`SimpleDateFormat`类的线程不安全主要源于以下几个原因: 1. **内部状态可变**:`SimpleDateFormat`内部维护了一些可变的状态,如解析和格式化日期时使用的日期字段和格式模板。当一个线程正在修改这些状态时,另...
"gethostbyname_r在某些linux版本中多线程不安全问题" 在 Linux 操作系统中,gethostbyname_r 函数是一个常用的 DNS 解析函数,但是,在某些 Linux 版本中,这个函数存在多线程不安全问题。本文将详细介绍这个问题...
线程安全变量则可以确保在多线程环境下,即使不使用锁,也可以安全地更新和读取这些变量。 在LabWindows/CVI的`多线程_线程锁_线程安全变量`示例中,你可能会发现以下几个关键点: 1. **线程创建与销毁**:使用`...
在当今的计算机科学领域,线程作为操作系统调度的最小单元,它允许一个进程同时派生出多个线程。这些线程独立执行,共享进程资源...开发人员应当时刻铭记线程安全的重要性,并将其作为设计多线程程序时的首要考虑因素。
3. 懒汉式(线程不安全): 第一次调用getInstance()方法时才实例化,如果多线程环境下,可能导致多个实例。 ```java public class Singleton { private static Singleton INSTANCE; private Singleton() {} ...
线程安全和同步线程是确保在多线程环境下正确执行的关键因素。线程安全指的是一个方法或类在多线程环境下可以正确无误地运行,不会因为线程之间的交互而导致数据的不一致或错误。同步线程则是指通过特定机制(如锁)...
综上所述,线程安全的单例模式实现是一个复杂的过程,需要综合考虑效率和线程安全两方面的因素。通过上述几种不同的实现方式,我们可以根据实际需求选择最适合的一种。其中,双重检查锁定因其较高的性能和线程安全性...
Java多线程-线程的安全问题与线程的同步机制介绍 在 Java 多线程编程中,线程安全问题是非常重要的一个话题。...通过了解线程安全问题的原因和解决方案,可以更好地编写多线程程序,避免线程安全问题的出现。
经常会看到说HashMap是线程不安全的,ConcurrentHashMap是线程安全的等等说法,不禁有个疑问,什么是线程安全?什么样的类是线程安全的? 1.什么是线程安全性(what) 线程安全定义,最核心是正确性, 正确性:多个...
内容概要:文章内容从原子性、可见性、有序性三个方面介绍C++线程安全问题的原因。通过原子操作、线程同步如互斥锁、读写锁、条件变量、信号量等方法解决C++线程安全问题。同时介绍了线程安全的单例,饿汉模式和懒汉...
本文档旨在从基础概念出发,详细介绍导致线程不安全的原因、如何避免线程不安全现象的发生,并提供具体的示例代码。 #### 基础概念 1. **线程(Thread)** - 线程是程序执行流的基本单位,是操作系统调度的最小...
java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...
在开发多线程应用时,线程安全成为至关重要的考量因素之一。特别是在需要处理并发任务时,如何确保线程之间的安全通信变得尤为重要。本篇文章将围绕一个具体的场景——项目中的巡检任务管理——深入探讨如何利用`...
- **线程安全问题原因:** - 因为同一个`Action`实例会被不同的HTTP请求重用,所以如果`Action`类中有成员变量(除了`transient`变量),那么这些成员变量就可能成为线程安全的问题点。 - 如果在`Action`类中定义...
在Java编程中,数据库操作是不可或缺的一部分,而有效管理数据库连接是提高系统性能的关键因素。线程安全的JDBC连接池就是为此目的设计的一种优化手段。在这个简单的实现中,我们利用了`ConcurrentLinkedQueue`数据...
在Java编程语言中,线程安全是多线程环境下编程时必须考虑的重要因素。线程安全的循环单链表是一种高效的数据结构,它允许在并发环境中进行插入、删除和遍历操作而不会出现数据不一致的情况。这篇博客文章将探讨如何...
浅谈Java StringBuilder为什么线程不安全 Java StringBuilder是一个可变的字符串对象,它可以动态地增加或删除字符,然而,它却不是线程安全的。在多线程环境下,使用StringBuilder可能会出现一些问题,例如输出值...
这就是使用后台线程的原因,比如使用`BackgroundWorker`组件或自定义线程。WFormsThread可能是一个示例,展示了如何在Windows Forms中正确处理线程,同时确保UI的响应性。 总结一下,本主题涵盖了C#中的线程控制...
SQLite本身并不提供完全的线程安全,这意味着在不同线程中并发访问数据库时,需要开发者自己处理同步问题。在Qt中,可以使用QMutex或QReadWriteLock等同步原语来保护对数据库的访问。 2. **数据库连接**: 每个...