成功的路上总是离不开贵人的帮助,名师的指点和小人的刺激。

莫怕,过了桥,就翻篇了

1.2.3实例变量与线程安全

自定义线程类中实例变量针对其他线程可以有共享与不共享的区分,这在多线程中的交互是一个技术点。

(1)不共享数据的情况

多个线程实例

 1 package com.cky.thread;
 2 
 3 /**
 4  * Created by chenkaiyang on 2017/11/27.
 5  */
 6 public class MyThreadTwo extends Thread{
 7 
 8     private int count = 5;
 9     public MyThreadTwo (String name) {
10         super();
11         this.setName(name);
12     }
13     @Override
14     public void run() {
15         super.run();
16         while(count > 0) {
17             count --;
18             System.out.println("由" +this.currentThread().getName() +"计算,count="+count);
19         }
20 
21     }
22 }

 

 1 package com.cky.test;
 2 
 3 import com.cky.thread.MyThreadTwo;
 4 
 5 /**
 6  * Created by chenkaiyang on 2017/11/27.
 7  */
 8 public class Test2 {
 9     public static void main(String[] args) {
10         MyThreadTwo a = new MyThreadTwo("A");
11         MyThreadTwo b = new MyThreadTwo("B");
12         MyThreadTwo c = new MyThreadTwo("C");
13         a.start();
14         b.start();
15         c.start();
16     }
17 }
D:\it\jdk1.8\bin\java -Didea.launcher.port=7533 "-Didea.launcher.bin.path=D:\it\idea\IntelliJ IDEA 2016.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\it\jdk1.8\jre\lib\charsets.jar;D:\it\jdk1.8\jre\lib\deploy.jar;D:\it\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\it\jdk1.8\jre\lib\ext\cldrdata.jar;D:\it\jdk1.8\jre\lib\ext\dnsns.jar;D:\it\jdk1.8\jre\lib\ext\jaccess.jar;D:\it\jdk1.8\jre\lib\ext\jfxrt.jar;D:\it\jdk1.8\jre\lib\ext\localedata.jar;D:\it\jdk1.8\jre\lib\ext\nashorn.jar;D:\it\jdk1.8\jre\lib\ext\sunec.jar;D:\it\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\it\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\it\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\it\jdk1.8\jre\lib\ext\zipfs.jar;D:\it\jdk1.8\jre\lib\javaws.jar;D:\it\jdk1.8\jre\lib\jce.jar;D:\it\jdk1.8\jre\lib\jfr.jar;D:\it\jdk1.8\jre\lib\jfxswt.jar;D:\it\jdk1.8\jre\lib\jsse.jar;D:\it\jdk1.8\jre\lib\management-agent.jar;D:\it\jdk1.8\jre\lib\plugin.jar;D:\it\jdk1.8\jre\lib\resources.jar;D:\it\jdk1.8\jre\lib\rt.jar;F:\springboot\threaddemo\out\production\threaddemo;D:\it\idea\IntelliJ IDEA 2016.3.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test2
由B计算,count=4
由C计算,count=4
由A计算,count=4
由C计算,count=3
由B计算,count=3
由C计算,count=2
由A计算,count=3
由C计算,count=1
由B计算,count=2
由C计算,count=0
由A计算,count=2
由B计算,count=1
由B计算,count=0
由A计算,count=1
由A计算,count=0

Process finished with exit code 0

结果分析,这里一共创建了3个线程实例,每个线程都有各自的count变量,各自递减自己的变量,这就说明这个是变量不共享,不存在多个线程共同访问同一个实例的情况。

(2)共享数据的情况

共享数据的情况就是多个线程可以访问同一个变量

 1 package com.cky.thread;
 2 
 3 /**
 4  * Created by chenkaiyang on 2017/11/27.
 5  */
 6 public class MyThreadThird  extends Thread{
 7     private int count = 5;
 8     @Override
 9     public void run() {
10         super.run();
11         count -- ;
12         System.out.println("由" + this.currentThread().getName()+"计算count="+count);
13     }
14 }
 1 package com.cky.test;
 2 
 3 import com.cky.thread.MyThreadThird;
 4 
 5 /**
 6  * Created by chenkaiyang on 2017/11/27.
 7  */
 8 public class Test3 {
 9     public static void main(String[] args) {
10         MyThreadThird mythread = new MyThreadThird();
11         Thread a = new Thread(mythread, "A");
12         Thread b = new Thread(mythread, "B");
13         Thread c = new Thread(mythread, "C");
14         Thread d = new Thread(mythread, "D");
15         Thread e = new Thread(mythread, "E");
16 
17         a.start();
18         b.start();
19         c.start();
20         d.start();
21         e.start();
22 
23 
24     }
25 }
1 D:\it\jdk1.8\bin\java -Didea.launcher.port=7534 "-Didea.launcher.bin.path=D:\it\idea\IntelliJ IDEA 2016.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\it\jdk1.8\jre\lib\charsets.jar;D:\it\jdk1.8\jre\lib\deploy.jar;D:\it\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\it\jdk1.8\jre\lib\ext\cldrdata.jar;D:\it\jdk1.8\jre\lib\ext\dnsns.jar;D:\it\jdk1.8\jre\lib\ext\jaccess.jar;D:\it\jdk1.8\jre\lib\ext\jfxrt.jar;D:\it\jdk1.8\jre\lib\ext\localedata.jar;D:\it\jdk1.8\jre\lib\ext\nashorn.jar;D:\it\jdk1.8\jre\lib\ext\sunec.jar;D:\it\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\it\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\it\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\it\jdk1.8\jre\lib\ext\zipfs.jar;D:\it\jdk1.8\jre\lib\javaws.jar;D:\it\jdk1.8\jre\lib\jce.jar;D:\it\jdk1.8\jre\lib\jfr.jar;D:\it\jdk1.8\jre\lib\jfxswt.jar;D:\it\jdk1.8\jre\lib\jsse.jar;D:\it\jdk1.8\jre\lib\management-agent.jar;D:\it\jdk1.8\jre\lib\plugin.jar;D:\it\jdk1.8\jre\lib\resources.jar;D:\it\jdk1.8\jre\lib\rt.jar;F:\springboot\threaddemo\out\production\threaddemo;D:\it\idea\IntelliJ IDEA 2016.3.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test3
2 由A计算count=3
3 由D计算count=0
4 由E计算count=1
5 由C计算count=2
6 由B计算count=3
7 
8 Process finished with exit code 0

结果分析,上面将一个线程对象传递到其他的线程中进行调用,相当于一个多个线程实例调用同一个线程对象,共享线程对象中的变量。

结果中A和B同时输出3,实际我们想要的结果是依次递减,产生了非线程安全的问题。

由于线程执行的随机性,所以产生了这样的结果,这时就需要让多个线程进行同步,也就是按顺序执行run方法里的内容,就是让一个线程执行完run方法里的代码后,再让cpu切换到另一个线程

使用synchronized关键字

 1 package com.cky.thread;
 2 
 3 /**
 4  * Created by chenkaiyang on 2017/11/27.
 5  */
 6 public class MyThreadThird  extends Thread{
 7     private int count = 5;
 8     @Override
 9     synchronized  public void run() {
10         super.run();
11         count -- ;
12         System.out.println("由" + this.currentThread().getName()+"计算count="+count);
13     }
14 }

再执行上面的test,结果如下(说明线程安全了)

D:\it\jdk1.8\bin\java -Didea.launcher.port=7536 "-Didea.launcher.bin.path=D:\it\idea\IntelliJ IDEA 2016.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\it\jdk1.8\jre\lib\charsets.jar;D:\it\jdk1.8\jre\lib\deploy.jar;D:\it\jdk1.8\jre\lib\ext\access-bridge-64.jar;D:\it\jdk1.8\jre\lib\ext\cldrdata.jar;D:\it\jdk1.8\jre\lib\ext\dnsns.jar;D:\it\jdk1.8\jre\lib\ext\jaccess.jar;D:\it\jdk1.8\jre\lib\ext\jfxrt.jar;D:\it\jdk1.8\jre\lib\ext\localedata.jar;D:\it\jdk1.8\jre\lib\ext\nashorn.jar;D:\it\jdk1.8\jre\lib\ext\sunec.jar;D:\it\jdk1.8\jre\lib\ext\sunjce_provider.jar;D:\it\jdk1.8\jre\lib\ext\sunmscapi.jar;D:\it\jdk1.8\jre\lib\ext\sunpkcs11.jar;D:\it\jdk1.8\jre\lib\ext\zipfs.jar;D:\it\jdk1.8\jre\lib\javaws.jar;D:\it\jdk1.8\jre\lib\jce.jar;D:\it\jdk1.8\jre\lib\jfr.jar;D:\it\jdk1.8\jre\lib\jfxswt.jar;D:\it\jdk1.8\jre\lib\jsse.jar;D:\it\jdk1.8\jre\lib\management-agent.jar;D:\it\jdk1.8\jre\lib\plugin.jar;D:\it\jdk1.8\jre\lib\resources.jar;D:\it\jdk1.8\jre\lib\rt.jar;F:\springboot\threaddemo\out\production\threaddemo;D:\it\idea\IntelliJ IDEA 2016.3.3\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.cky.test.Test3
由A计算count=4
由E计算count=3
由D计算count=2
由C计算count=1
由B计算count=0

Process finished with exit code 0

结果分析:

synchronized可以在任意对象及方法上枷锁,而加锁的这段代码叫做互斥区

总结:当一个线程想要执行同步方法里的代码,首先线程会尝试拿这把锁,如果能拿到这把锁,那么这个线程就能执行synchronize里的代码,如果拿不到这把锁,这个线程就会不断尝试那这把锁

,直到拿到为止,而且是多个线程同时去争抢这个锁

非线程安全:多个线程对同一个对象中的同一个实例变量进行操作出现值被更改,值不同步,出现影响程序执行流程的情况。

 

posted on 2017-12-02 15:43  痞子陈2016  阅读(238)  评论(0编辑  收藏  举报

导航