同步与死锁

在多线程的开发中,同步与死锁的概念非常重要

 

class MyThread implements Runnable{
    private int ticket = 5 ;    // 假设一共有5张票
    public void run(){
        for(int i=0;i<100;i++){
            if(ticket>0){    // 还有票
                try{
                    Thread.sleep(300) ;    // 加入延迟
                }catch(InterruptedException e){
                    e.printStackTrace() ;
                }
                System.out.println("卖票:ticket = " + ticket-- );
            }
        }
    }
};
public class SyncDemo01{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 定义线程对象
        Thread t1 = new Thread(mt) ;    // 定义Thread对象
        Thread t2 = new Thread(mt) ;    // 定义Thread对象
        Thread t3 = new Thread(mt) ;    // 定义Thread对象
        t1.start() ;
        t2.start() ;
        t3.start() ;
    }
};
View Code

要想解决资源共享的同步操作问题,可以使用同步代码块和同步方法两种方式完成

 

普通代码块:直接定义在方法之中

构造块:直接定义在类中,优先于构造方法执行,可重复调用

静态块:使用static关键字声明的,优先于构造块执行,只执行一次,在类加载时执行

同步代码块:使用synchronized关键字声明的代码块

 

同步的时候必须指明同步的对象,一般情况下会将当前对象作为同步的对象,使用this表示

class MyThread implements Runnable{
    private int ticket = 5 ;    // 假设一共有5张票
    public void run(){
        for(int i=0;i<100;i++){
            synchronized(this){    // 要对当前对象进行同步
                if(ticket>0){    // 还有票
                    try{
                        Thread.sleep(300) ;    // 加入延迟
                    }catch(InterruptedException e){
                        e.printStackTrace() ;
                    }
                    System.out.println("卖票:ticket = " + ticket-- );
                }
            }
        }
    }
};
public class SyncDemo02{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 定义线程对象
        Thread t1 = new Thread(mt) ;    // 定义Thread对象
        Thread t2 = new Thread(mt) ;    // 定义Thread对象
        Thread t3 = new Thread(mt) ;    // 定义Thread对象
        t1.start() ;
        t2.start() ;
        t3.start() ;
    }
};
View Code

从运行结果可以发现,加入同步操作后,不会产生负数的情况,但是,程序的执行效率明显降低很多

 

class MyThread implements Runnable{
    private int ticket = 5 ;    // 假设一共有5张票
    public void run(){
        for(int i=0;i<100;i++){
            this.sale() ;    // 调用同步方法
        }
    }
    public synchronized void sale(){    // 声明同步方法
        if(ticket>0){    // 还有票
            try{
                Thread.sleep(300) ;    // 加入延迟
            }catch(InterruptedException e){
                e.printStackTrace() ;
            }
            System.out.println("卖票:ticket = " + ticket-- );
        }

    }
};
public class SyncDemo03{
    public static void main(String args[]){
        MyThread mt = new MyThread() ;    // 定义线程对象
        Thread t1 = new Thread(mt) ;    // 定义Thread对象
        Thread t2 = new Thread(mt) ;    // 定义Thread对象
        Thread t3 = new Thread(mt) ;    // 定义Thread对象
        t1.start() ;
        t2.start() ;
        t3.start() ;
    }
};
View Code

 

 

死锁:

资源共享时需要进行同步操作!

程序中过多的同步会产生死锁!

 

引用菲菲的一段话,就是十个人十支筷子吃饭,人要想吃饭就必须要有两支筷子,那么必须要有人放下筷子给别人使用才能吃饭,那么如果十个人都在等待着 别人放 下筷子,那么谁也吃不到饭,就出现了死锁现象。就像两个人打架,一个人在楼上喊道:“你上来!”另一个人在楼下喊道:“你下来!”一样。。。。。

 

例如:

class Zhangsan{    // 定义张三类
    public void say(){
        System.out.println("张三对李四说:“你给我画,我就把书给你。”") ;
    }
    public void get(){
        System.out.println("张三得到画了。") ;
    }
};
class Lisi{    // 定义李四类
    public void say(){
        System.out.println("李四对张三说:“你给我书,我就把画给你”") ;
    }
    public void get(){
        System.out.println("李四得到书了。") ;
    }
};
public class ThreadDeadLock implements Runnable{
    private static Zhangsan zs = new Zhangsan() ;        // 实例化static型对象
    private static Lisi ls = new Lisi() ;        // 实例化static型对象
    private boolean flag = false ;    // 声明标志位,判断那个先说话
    public void run(){    // 覆写run()方法
        if(flag){
            synchronized(zs){    // 同步张三
                zs.say() ;
                try{
                    Thread.sleep(500) ;
                }catch(InterruptedException e){
                    e.printStackTrace() ;
                }
                synchronized(ls){
                    zs.get() ;
                }
            }
        }else{
            synchronized(ls){
                ls.say() ;
                try{
                    Thread.sleep(500) ;
                }catch(InterruptedException e){
                    e.printStackTrace() ;
                }
                synchronized(zs){
                    ls.get() ;
                }
            }
        }
    }
    public static void main(String args[]){
        ThreadDeadLock t1 = new ThreadDeadLock() ;        // 控制张三
        ThreadDeadLock t2 = new ThreadDeadLock() ;        // 控制李四
        t1.flag = true ;
        t2.flag = false ;
        Thread thA = new Thread(t1) ;
        Thread thB = new Thread(t2) ;
        thA.start() ;
        thB.start() ;
    }
};
View Code

 张三说了话等待李四回应,李四说了话也等待张三回应,于是。。。。。死锁了。。。。。

也就是说,死锁一般就是表示进程间互相等待对方执行,现在谁也不执行的情况。

 

 

问题描述:死锁问题应该是这样发生的。情景:两个人,一个厕所。情节:里面的人办完事了,可是忘了带纸,就给外面的人要纸,外面的人不给,于是乎,出不 来;这外面一个人有纸急冲冲的要办事,可是进不去,说里面的人,赶紧出来,可是里面的人没有纸怎么出的来。于是,就这样两个人僵持着。问题的原因在于,里 面的人等着外面的人给他纸,外面的人等着里面的人给让位,各自需要的资源被占用了,于是死锁就发生了。

public class DeadLock implements Runnable{
        //设置标识符
        public int flag = 1;
        //创建两个Object对象
        static Object o1 = new Object();
        static Object o2 = new Object();
        //重写run方法
        public void run (){
            System.out.println("flag = "+flag);
            if(flag == 1){
                //当flag的值为1时,锁定o1,睡眠5ooms,然后执行o2
                synchronized(o1){
                    try {
                        Thread.sleep(500);
                        System.out.println("i am o1");   
                    }
                    catch( Exception e) {
                        System.out.println("error!");
                    }
               
                    synchronized(o2){
                        System.out.println("o2");
                    }
                }
            }
           
            if(flag == 0 ){
                //当flag的值为0时,锁定o2,睡眠5ooms,然后执行o1
                synchronized(o2){
                    try {
                        Thread.sleep(500);
                    System.out.println("i am o2");
                   
                    }
                    catch( Exception e) {
                        System.out.println("error!");
                    }
                    synchronized(o1){
                        System.out.println("o1");
                    }
                }
            }
        }
        public static void main(String args[]){
            DeadLock dl1 = new DeadLock();
            DeadLock dl2 = new DeadLock();
            //为各自对象的标识符赋值
            dl1.flag = 0;
            dl2.flag = 1;
            Thread t1 = new Thread(dl1);
            Thread t2 = new Thread(dl2);
            //两个线程启动,各自调用run方法,这样的话各自需要的资源被占用,死锁发生
            t1.start();
            t2.start();
        }
    } 
View Code

 

 

同步,,就是多线程访问同一个资源,存在安全问题,,就必须加同步就是上锁嘛,一次只能有一个线程访问一个资源,这个线程访问完出来后,别的线程才有资格去访问,不然线程的切换 会造成安全隐患。。。
死锁,,是发生在同步的基础上的,就是说 有两个以上资源,分别加了同步,然后多个线程分别访问不同资源的时候 由于每个锁里面是相互有联系的,,这几个线程就在里面 不能访问资源,就阻塞在里面了,,说的通俗点 就是占着茅坑不拉屎,,,然后外面排队的人进不去,,里面的人也出不来,,那么程序就卡在那里了,,不人为干涉,,程序不就结束的

posted @ 2015-03-10 11:53  闲来垂钓  阅读(219)  评论(0)    收藏  举报