多线程以及同步问题

1.单例中的线程安全问题

在单例设计模式中,会出现多线程的同步问题。主要表现在,当使用的是懒汉式单例设计模式来创建对象的时候,若有多个进程同时在执行,则有可能会创建了多个对象,但这个不是单例设计模式应该出现的问题。所以需要使用锁机制来解决。需要注意的是,饿汉式不会出现这个问题。具体代码如下。

 1 class Singleton_lazy{
 2     //懒汉式
 3     private Singleton_lazy(){}
 4     
 5     private static Singleton_lazy INSTANCE = null;
 6     
 7     public static Singleton_lazy getInstance(){
 8         if(INSTANCE == null){                 //在同步代码块的上面加一个判断,若对象不为空,则肯定不需要创建对象了。也就不需要再去通过同步代码块了
 9             synchronized (Singleton_lazy.class) {     //因为是静态的方法,没有办法使用this去作为锁的对象,因此可以使用类名.class
10                 if (INSTANCE == null)
11                     INSTANCE = new Singleton_lazy();
12             }
13         }
14         return INSTANCE;
15     }
16 }

姑且也许可以这么认为,在有判断语句存在的地方,由于多线程是由cpu来控制执行的,时间片的切换可能导致一种不安全的情况,例如

1 boolean flag = false;
2 if(flag == false){
3 ....execute;
4 flag = true;
5 }

 

在这种情况下,第一个线程满足条件进入之后,还没来得及将flag改为true,此时第二条进程已经通过了判断,进入了函数体,导致不安全问题的产生。

 

2.死锁问题

 1 public class _02_DeadLock {
 2 
 3     public static void main(String[] args) throws Exception {
 4         //创建一个任务类的对象
 5         DeadLockTask task = new DeadLockTask();
 6         //创建线程类对象
 7         /*
 8          * 如果这样去写死锁的话,会出现一个问题,
 9          * 一旦中国人或者美国人拿到了第一次的线程的执行权限,那么就会一直拿下去,另一个进程就没有机会再能够拿到了。并且让标记改为false,这样就
10          * 有可能进入到美国人线程的循环中
11          * 因此:当中国人线程开始执行之后,让主线程睡一会儿。这样的话,另一个线程就有机会能够执行。
12          */
13         Thread chineseThread = new Thread(task,"中国人线程");
14         Thread americanThread = new Thread(task,"美国人线程");
15         chineseThread.start();
16         Thread.sleep(1000);    //这边要让主线程睡一会儿,才能够让后面的线程有机会执行。
17         task.flag = false;
18         americanThread.start();
19     }
20 
21 }
22 
23 //创建一个死锁任务类
24 class DeadLockTask implements Runnable{
25     //属性
26     //定义一个flag用来记录到底是中国人还是美国人,true代表中国人
27     boolean flag = true;
28     //此时定义两个锁对象
29     Object Chopsticks = new Object();
30     Object KnifeAndFork = new Object();
31     //行为
32     @Override
33     public void run() {
34         //死锁的主要的产生的原因就是同步嵌套了同步。那么为了形成死锁,我们这边要人为制造同步的嵌套
35         //注意:而且不能只拿一次就结束了。要制造一个无限的一直去拿的情况 
36         if(flag){
37             while(true){
38                 synchronized (Chopsticks){
39                     System.out.println(Thread.currentThread().getName() + "chinese...get...chopsticks");
40                     synchronized(KnifeAndFork){
41                         System.out.println(Thread.currentThread().getName() + "chinese...get....knifeandfork");
42                     }
43                 }
44             }
45         }else{
46             while(true){
47                 synchronized(KnifeAndFork){
48                     System.out.println(Thread.currentThread().getName() + "american...get...knifeandfork");
49                     synchronized(Chopsticks){
50                         System.out.println(Thread.currentThread().getName() + "american...get...chopsticks");
51                     }
52                 }
53             }
54         }
55     }
56 }

 

posted @ 2017-04-04 23:57  leevanes  阅读(316)  评论(0编辑  收藏  举报