产生线程安全的原因:
1、多个线程操作共享数据
2、操作共享数据的线程代码有多条
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算就会导致线程安全的产生。
比如:
当我们每个线程进入判断语句时候我让他睡眠10毫秒,那比如此时num为2的时候,有4个线程在执行,
其中线程1进如判断语句了值为2
其中线程2进如判断语句了值为2
其中线程3进如判断语句了值为2
其中线程4进如判断语句了值为2
当进行票数相减时候其中一个线程执行完毕为1
那另一个线程不是出现了-1,这个时候就出现问题了
public class ThreadExplain implements Runnable{
private int num = 100;
public void show(){
while (true){
if(num>0){
try {
Thread.sleep(10);//当每个线程运行到这里的时候我让线程睡眠10毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"当前票数为"+num--);
}
}
}
@Override
public void run() {
show();
}
}
public static void main(String[] args){
ThreadExplain t = new ThreadExplain();
Thread th1 = new Thread(t);
Thread th2 = new Thread(t);
Thread th3 = new Thread(t);
Thread th4 = new Thread(t);
th1.start();
th2.start();
th3.start();
th4.start();
}
解决办法:
用同步代码块来解决;
格式:synchronized(对象){
}
同步弊端:效率会有影响
public class ThreadExplain implements Runnable{
private int num = 100;
Object object = new Object();
public void show(){
while (true){
synchronized (object){
if(num>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"当前票数0"+num--);
}
}
}
}
@Override
public void run() {
show();
}
}
除了同步代码块还可以用同步函数,只是开发一般用同步代码块
同步代码块与同步函数的区别,
同步代码块的锁是任意对象,同步函数的锁是this
public class ThreadExplain implements Runnable{
private int num = 100;
Object object = new Object();
public void show(){
while (true){
/*synchronized (object){
if(num>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"当前票数0"+num--);
}
}*/
synfunction();
}
}
public synchronized void synfunction(){
if(num>0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"当前票数0"+num--);
}
}
@Override
public void run() {
show();
}
}