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是线程不安全的,ConcurrentHashMap是线程安全的等等说法,不禁有个疑问,什么是线程安全?什么样的类是线程安全的? 1.什么是线程安全性(what) 线程安全定义,最核心是正确性, 正确性:多个...
内容概要:文章内容从原子性、可见性、有序性三个方面介绍C++线程安全问题的原因。通过原子操作、线程同步如互斥锁、读写锁、条件变量、信号量等方法解决C++线程安全问题。同时介绍了线程安全的单例,饿汉模式和懒汉...
java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...
c_safe_lib c线程安全库,这个项目的目的是创造一套可以工程使用的c数据结构库,在实际工程中一套优秀高效的数据结构库是必不可少的。主要解决俩个方面:1.线程安全2.跨平台 linux 、windows实现原理功能状态实现原理...
1.多线程的执行顺序无法保证,与操作系统的调度策略和线程优先级等因素有关。 2.多线程的切换可能发生在任何时刻、任何地点。 3.多线程对代码的敏感度高,因此对代码的细微修改都可能产生意想不到的效果。 先由一...
在计算机处理器发展为包含越来越多的核心的时期,多线程是创建可伸缩性、高效的、高响应性应用程序的关键因素。如果你没有正确地使用多线程,它会导致难以捉摸的问题,需要你花费大量时间去解决。因此,现代应用程序...
首先使用设计模式中的单件模式,防止多次初始化对象,...此程序会增加三次运算,原因是本线程未到200次,但是必然会有一个线程第一次增加所以在add里再做判断 http://blog.csdn.net/ggbb190/article/details/18003165
关于多线程技术的精华总结,从创建到具体如何应用以及使用多线程的原因及其价值,适合初学者快速理解这部分内容以及开发具体的程序。
Java线程CPU占用高原因排查方法,Java线程CPU占用高原因排查方法
线程同步,指一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时其它线程为保证数据一致性,不能调用该功能。 举例1: 银行存款 5000。柜台,折:取3000;提款机,卡:取 3000。剩余:2000 举例2...
线程问题总结:多线程实现方式、线程控制、多线程安全问题以及解决方法、单例懒汉式的线程安全问题、死锁出现的原因
编写原因:鉴于VB创建稳定线程的需求 特点:可替代API CreateThread来创建线程,且自动对线程进行初始化,线程函数中不再需要初始化线程就可以使用对象、类、窗口等。提供多达四个线程参数,如果不够用的可通过...
木马远程线程插入,进行对电脑的远程控制,从而控制别人电脑,对于杀毒软件可以检测并结束其进程
需要用锁,来保证其线程安全性:原因:多个线程可能进入判断是否已经存在实例的if语句,从而non thread safety. 使用double-check来保证thread safety.但是如果处理大量数据时,该锁才成为严重的性能瓶颈。 ...
目录SimpleDateFormat诡异bug复现SimpleDateFormat诡异bug字符串日期转Date日期(parse)Date日期转String类型(format)SimpleDateFormat出现bug的原因如何解决SimpleDateFormat多线程安全问题局部变量使用...
线程的同步与阻塞: 引入多线程访问共享资源可能导致的问题,如竞态条件和数据不一致。介绍如何使用 synchronized 关键字来实现线程的同步和阻塞。 线程间通信: 详解线程间通信的方法,包括 wait、notify 和 ...
明白死锁产生的原因,在程序中演示死锁产生并从而实现多线程陈旭解决死锁(deadlock)这一类问题。
C#用了多线程界面卡死
这就有可能导致A线程和B线程同时对一个数组扩容,A线程扩容后替换掉老数组,这时B线程使用的数组实际上是A线程扩容后的数组,就会产生线程安全问题。 死锁原因 比如,当前集合数组长度为2,已经有两个元素被放在了...
实现消息队列的关键因素是考量不同线程访问消息队列的同步问题。本实现涉及到几个知识点 std::lock_guard 介绍 std::lock_gurad 是 C++11 中定义的模板类。定义如下: template <class> class lock_guard; lock_...