如何处理线程并发时产生的线程安全问题(Runnable和Thread)
来源:互联网 发布:淘宝网9.9包邮 编辑:程序博客网 时间:2024/05/22 13:33
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runnable接口。多线程执行没有一个确定的顺序,并不是先启动线程一定先执行,当前一刻,谁抢占了cpu资源,谁就执行
一.实现runnable接口
位于同一个Thread对象里,t1,t2两条线程的run()方法,其实是一个run(),都在调用静态方法区的sum,将会导致线程安全问题
public class Class2 { public static void main(String args[])throws Exception{ class3 r=new class3(); Thread t1=new Thread(r); Thread t2=new Thread(r); t1.start(); t1.join();//如果join()位于此处会引发线程安全问题,结果混乱 t2.start(); t2.join(); System.out.println(class3.sum); }}class class3 implements Runnable{ public static int sum=0; public void add(){ for(int i=0;i<5000;i++){ sum=sum+1; } } public void run(){ add(); }}//结果为10000。当t1.start()之后接t1.join()之后结果为10000。同一线程不能启动多次
同步锁
加了同步锁的方法或代码段,在同一时刻,只允许获得当前锁对象的一条线程执行,执行完成后,释放锁对象。
1.动态方法同步锁,锁对象为当前实例对象
public class Class2 { public static void main(String args[])throws Exception{ class3 r=new class3(); Thread t1=new Thread(r); Thread t2=new Thread(r); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(class3.sum); }}class class3 implements Runnable{ public static int sum=0; public synchronized void add(){//动态方法同步锁 for(int i=0;i<5000;i++){ sum=sum+1; } } public void run(){ add(); }}//结果为10000,解决了线程安全问题
2静态方法同步锁,锁对象为当前类
public class Class2 { public static void main(String args[])throws Exception{ class3 r=new class3(); Thread t1=new Thread(r); Thread t2=new Thread(r); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(class3.sum); }}class class3 implements Runnable{ public static int sum=0; public static synchronized void add(){//静态方法同步锁 for(int i=0;i<5000;i++){ sum=sum+1; } } public void run(){ add(); }}//结果为10000,解决了线程安全问题
3代码段同步锁,自定义锁对象(动态/静态)
public class Class2 { public static void main(String args[])throws Exception{ class3 r=new class3(); Thread t1=new Thread(r); Thread t2=new Thread(r); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(class3.sum); } }class class3 implements Runnable{ public static int sum=0; public Object lock=new Object(); public void add(){ synchronized(lock){ for(int i=0;i<5000;i++){ sum=sum+1; } } } public void run(){ add(); }}//结果为10000,解决了线程安全问题
二,Thread类
join() 方法,它能够使调用该方法的线程在此之前执行完毕。
如果不使用t.join()方法,主线程main方法的System.out.println(a);语句将抢先执行。当主线程 main方法执行System.out.println(a);这条语句时,线程还没有真正开始运行,或许正在为它分配资源准备运行。因为为线程分配资源需要时间,而main方法执行完t.start()方法后继续往下执行System.out.println(a);,这个时候得到的结果是a还没有被 改变的值0 。
由上图可知,有t1,t2两个不同的对象,他们各自有各自的run()方法,如果只是锁定run(synchronized add();),仍然会导致线程安全问题
public class Mydemo { public static void main(String[] args)throws Exception{ Mydemo1 r=new Mydemo1(); r.start(); System.out.println(Mydemo1.sum); }}class Mydemo1 extends Thread{ public static int sum=0; public void add(){ for(int i=0;i<5000;i++){ sum=sum+1; } } public void run(){ add(); }}//输出的结果为0,由此可知join()方法的重要性
有join()方法
public class Mydemo { public static void main(String[] args)throws Exception{ Mydemo1 r=new Mydemo1(); Mydemo1 r1=new Mydemo1(); r.start(); r.join(); r1.start(); r1.join(); System.out.println(Mydemo1.sum); }}class Mydemo1 extends Thread{ public static int sum=0; public void add(){ for(int i=0;i<5000;i++){ sum=sum+1; } } public void run(){ add(); }}//结果为10000.当r.start()后不接r.join()时出现不确定数字
动态同步锁
public class Mydemo { public static void main(String[] args)throws Exception{ Mydemo1 r=new Mydemo1(); Mydemo1 r1=new Mydemo1(); r.start(); r1.start(); r.join(); r1.join(); System.out.println(Mydemo1.sum); }}class Mydemo1 extends Thread{ public static int sum=0; public synchronized void add(){ for(int i=0;i<5000;i++){ sum=sum+1; } } public void run(){ add(); }}//结果为不确定数字,因为r,r1为不同对象,锁住的是各自的add()方法,使用的还是同一个静态区的变量,仍会出现并发线程安全问题
静态同步锁
public class Mydemo { public static void main(String[] args)throws Exception{ Mydemo1 r=new Mydemo1(); Mydemo1 r1=new Mydemo1(); r.start(); r1.start(); r.join(); r1.join(); System.out.println(Mydemo1.sum); }}class Mydemo1 extends Thread{ public static int sum=0; public static synchronized void add(){ for(int i=0;i<5000;i++){ sum=sum+1; } } public void run(){ add(); }}//加上static 之后使add()方法位于静态区,公共的大家都可以调用,加上静态锁后谁先抢占后先执行后面一个再执行
阅读全文
1 0
- 如何处理线程并发时产生的线程安全问题(Runnable和Thread)
- 多线程Runnable和Thread产生线程
- 线程(Thread) 和 Runnable
- java线程---Runnable和Thread的区别
- Java线程-Runnable和Thread的区别
- java线程---Runnable和Thread的区别
- Java 线程 Runnable和Thread的区别
- 线程Thread和Runnable的区别
- 线程创建Thread和Runnable
- Thread和Runnable创建线程
- Thread--01在线程池使用Callable和Runnable的区别以及如何关闭线程
- 线程的创建(Runnable,Thread)
- 线程并发学习----Thread、Runnable、Callable
- java线程系列---Runnable和Thread的区别、线程同步
- 线程--Thread和Runnable创建线程的区别
- Runnable Thread 线程的实现
- (十)java并发编程--创建和启动线程(java.lang.Thread 、java.lang.Runnable)
- SpringMVC和Struts2并发访问时的线程安全问题
- 历史
- 一起来写个弹幕
- [系分] 逻辑架构和包图
- bzoj 3307: 雨天的尾巴 (线段树合并+LCA)
- Linux下Eclipse给工程配置(附加库目录)
- 如何处理线程并发时产生的线程安全问题(Runnable和Thread)
- 数据结构---线索二叉树
- C# Word文档打印方法
- 定时器-图片或者文字上下播放
- TF/06_Neural_Networks/05 06 07 08
- 终于有自己的博客了
- 【Hibernate】——常用主键生成策略
- HotSpot虚拟机在java堆中的内存使用
- python3进阶学习总结——简单爬虫实现