这一章节我们来简单讨论一下共享变量与线程安全简介。
1.共享变量
没有共享的代码:
package com.ray.deepintothread.ch01.topic_2;
public class NotShareTheVariables {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
RunnableTwo runnableTwo = new RunnableTwo();
Thread thread = new Thread(runnableTwo);
thread.start();
}
}
}
class RunnableTwo implements Runnable {
private int count = 5;
@Override
public void run() {
while (count > 0) {
System.out.println("由线程" + Thread.currentThread().getName() + "计算 " + count--);
}
}
}
输出:
由线程Thread-0计算 5
由线程Thread-0计算 4
由线程Thread-0计算 3
由线程Thread-0计算 2
由线程Thread-0计算 1
由线程Thread-2计算 5
由线程Thread-2计算 4
由线程Thread-2计算 3
由线程Thread-2计算 2
由线程Thread-1计算 5
由线程Thread-2计算 1
由线程Thread-1计算 4
由线程Thread-1计算 3
由线程Thread-1计算 2
由线程Thread-1计算 1
从代码我们可以看见,其实我们建立了3个任务(笔者比较喜欢用任务来命名放入线程里面的Target),分别使用三个线程来执行,因此每一个线程所输出的结果是连续的。
从输出我们可以看见,cup执行线程任务的分配是随机的,是按照cup的调度算法来分配,因此输出呈现出随机状态。
共享变量的代码:
package com.ray.deepintothread.ch01.topic_2;
public class AnsychThread {
public static void main(String[] args) {
RunnableThree runnableThree = new RunnableThree();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(runnableThree);
thread.start();
}
}
}
class RunnableThree implements Runnable {
private int count = 5;
@Override
public void run() {
System.out.println("由线程" + Thread.currentThread().getName() + "计算 " + count--);
}
}
输出:
由线程Thread-0计算 5
由线程Thread-2计算 3
由线程Thread-1计算 4
由线程Thread-3计算 2
由线程Thread-4计算 1
上面的代码是这样的,建立一个任务,然后由5个线程同时执行这个任务。
从上面的输出可以看到,当5个线程同时执行一个任务的时候,它将会共享任务实例的变量,而且由于“--”的过程分为三步,第一步是取值,第二步是想减,第三步是赋值,而且这三步没有同步,因此很可能当线程1取值的之后,就被线程2想减,因此会造成输出的混乱。
上面的代码就会引起线程安全的问题。
共享变量并同步的代码:
package com.ray.deepintothread.ch01.topic_2;
public class SychThreadWithTag {
public static void main(String[] args) {
RunnableFour runnableFour = new RunnableFour();
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(runnableFour);
thread.start();
}
}
}
class RunnableFour implements Runnable {
private int count = 5;
@Override
public synchronized void run() {
System.out.println("由线程" + Thread.currentThread().getName() + "计算 " + count--);
}
}
输出:
由线程Thread-0计算 5
由线程Thread-2计算 4
由线程Thread-1计算 3
由线程Thread-4计算 2
由线程Thread-3计算 1
由于我们加上了synchronized关键字作同步,因此每一次“--”只有一个线程,其他线程均不能够进入里面操作,因此,输出会变得有序。
总结:这一章节简单介绍了一下共享变量与线程安全。