Java多线程学习笔记(二)

三 多线程执行的共享数据和非共享数据:

共享数据:就是每个线程执行的时候共享数据使用,比如这个线程一个为5的数据,减少为4之后,另一个线程执行拿到的数据是4,两个线程执行的数据是共享的。

非共享数据:各个线程执行的数据不受其他线程数据的改变而改变。

1 非共享数据:

 1 package link.summer7c.test;
 2 
 3 public class Test{
 4     public static void main(String[] args){
 5         MyThread2 a=new MyThread2("A");
 6         MyThread2 b=new MyThread2("B");
 7         MyThread2 c=new MyThread2("C");
 8         a.start();
 9         b.start();
10         c.start();
11     }
12 }
13 class MyThread2 extends Thread{
14     private int count=5;
15     public MyThread2(String name){
16         super();
17         this.setName(name);
18     }
19     public void run(){
20         super.run();
21         while(count>0){
22             count--;
23             System.out.println(this.currentThread().getName()+":count:"+count);
24         }
25     }
26 }

程序运行结果为:

C:count:4
B:count:4
A:count:4
B:count:3
C:count:3
C:count:2
C:count:1
C:count:0
B:count:2
A:count:3
B:count:1
A:count:2
B:count:0
A:count:1
A:count:0

从结果我们可以看见,3个线程的数据之间互不影响,变量减少按照各自的减法进行。这就是非共享的数据,这种做法通常在一些多线程并发操作中使用,各个数据没有相互影响。

2 共享数据:

各个线程之间的数据是共享的,他们的数据受其他线程的运行而影响。

 1 package link.summer7c.test;
 2 
 3 public class Test{
 4     public static void main(String[] args){
 5         MyThread3 myThread=new MyThread3();
 6         Thread a=new Thread(myThread,"A");
 7         Thread b=new Thread(myThread,"B");
 8         Thread c=new Thread(myThread,"C");
 9         a.start();
10         b.start();
11         c.start();
12     }
13 }
14 class MyThread3 extends Thread{
15     private int count=4;
16         public void run(){
17             super.run();
18         count--;
19           System.out.println(this.currentThread().getName()+":count:"+count);
20     }
21 }    

运行结果有很多种:

A:count:3
B:count:2
C:count:1

或者:

A:count:2
B:count:2
C:count:1

这种运行结果可能会发现有些问题,就是出现了相同的数据。

这个之后来讨论。

构造方法public Thread(Runnable target, String name)

共享数据的main方法中并不是new了多个对象,而是new个一个我们的类,然后new了3个Thread对象,调用了public Thread(Runnable target, String name)构造方法。

共享数据的时候还要不能出现循环,如果一个线程开始循环,那么其他循环就得不到运行的机会了。

三 线程安全的问题

在共享数据的时候,我们会看到多个运行及结果很奇特,比如在运行的时候会出现2个相同的数据,这就牵扯到了线程安全的问题,如果在多线程中出现了:

A:count:2
B:count:2
C:count:1

这种情况,就称作线程不安全。举个例子,我们再抢火车票,每个客户都是一个线程,那么我们需要线程之间是安全的,不然就会发生两个座位同时被买走的可能性,发生这样的情况很不好。为了解决线程安全性我们可以使用同步锁,也就是每个线程之间要同步数据,不能发生线程之间不同步导致的线程不安全情况。多线程之间的同步可以通过在run方法之前加入synchronized关键字来实现,这样就不会出现两个数据相同的情况了。

class MyThread3 extends Thread{
    private int count=4;
    synchronized public void run(){
        super.run();
        count--;
        System.out.println(this.currentThread().getName()+":count:"+count);
    }
}

synchronized可以在任意对象和方法上加锁,加锁的代码称为“互斥区”或者临界区。加上锁之后线程会是这样的:

程序运行->拿锁->如果拿到锁了执行synchronized里的代码

       ->如果没有拿到就不断的尝试知道拿到->执行synchronized里的代码

=========================================

原文地址:https://www.cnblogs.com/Summer7C/p/5004909.html