package study_02;
public class unsafeThread{
public static void main(String[] args) {
Web12306 web12306 = new Web12306();
new Thread(web12306,"线程A").start();
new Thread(web12306,"线程B").start();
new Thread(web12306,"线程C").start();
}
}
class Web12306 implements Runnable{
private int ticketNum = 10;
private boolean flag = true;
@Override
public void run() {
test();
}
public void test() {
while (flag) {
if (ticketNum <= 0) {
flag = false;
break;
}else {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "----->"+ ticketNum--);
}
}
}
}
运行后会发现
线程C----->9
线程A----->9
线程B----->10
线程A----->8
线程C----->8
线程B----->7
线程A----->6
线程B----->5
线程C----->6
线程A----->4
线程C----->3
线程B----->4
线程A----->2
线程C----->2
线程B----->2
线程C----->1
线程A----->-1
线程B----->0
出现两个9 还会出现-1这样的情况,这就是线程不安全
出现两个9是因为每个线程都有自己独立的工作空间,他们都和主存打交道,主存的ticketNum=10,每个线程把ticketNum=10拷贝到各自的工作空间里,当线程A获得ticketNum为10后拷贝到自己的工作空间里,然后进行IO操作,这是ticketNum还是为10.这时线程C被CPU调用,也获得tickNum为10拷贝到自己的空间,这时A重新被调用,然后修改tickNum数值,把ticketNUm减1改成9,线程C之后也被重新调用,把tickNum减1改成9.
出现-1是因为当还有一张票时,线程C被调用看到还有一张票,获得ticketNum= 1,然后进行10ms的IO操作,这时ticketNum还没有被修改还是为1,此时在线程B进行IO操作时,线程B也看到余票还有1,再次进入IO操作,同理线程C也是,当线程C重新被调用,对ticketNum减一,然后线程B被调用对ticketNum减一,同理线程A也是,最后显示线程C为1 线程B为0,线程A为-1.
package study_3;
/*
* 同步方法 同步块
*
*
*
*/
public class synTest2{
public static void main(String[] args) {
synWeb12306 web12306 = new synWeb12306();
new Thread(web12306,"线程A").start();
new Thread(web12306,"线程B").start();
new Thread(web12306,"线程C").start();
}
}
class synWeb12306 implements Runnable{
private int ticketNum = 10;
private boolean flag = true;
@Override
public void run() {
test();
}
public synchronized void test() {// 线程安全 同步方法 锁的是对象的资源
while (flag) {
try {
Thread.sleep(100);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (ticketNum <= 0) {
flag = false;
break;
}else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "------>" +ticketNum--);
}
}
}
}
线程A------>10
线程A------>9
线程A------>8
线程A------>7
线程A------>6
线程A------>5
线程A------>4
线程A------>3
线程A------>2
线程A------>1
package study_02;
import java.util.ArrayList;
import java.util.List;
public class unsafeThread4 {
public static void main(String[] args) throws InterruptedException {
List list = new ArrayList();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(1000);//list里的元素数量
System.out.println(list.size());
}
}
结果为9998,按理来说应该为10000这是加同步锁,同步块
package study_02;
import java.util.ArrayList;
import java.util.List;
public class unsafeThread4 {
public static void main(String[] args) throws InterruptedException {
List list = new ArrayList();
for (int i = 0; i < 10000; i++) {
new Thread(()->{
synchronized (list) {//同步块
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(1000);//list里的元素数量
System.out.println(list.size());
}
}