A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

本帖最后由 逆风TO 于 2020-3-10 11:22 编辑

解决多线程当中共享资源冲突的问题1. 冲突问题展示:
[Java] 纯文本查看 复制代码
/*
 * 共享资源冲突的问题
 */
class SingleThread implements Runnable {

        // 共享资源,100张票
        private static int ticket = 100;

        @Override
        public void run() {
                while (true) {
                        if (ticket > 0) {
                                System.out.println(Thread.currentThread().getName() +
                                 "售出了第" + ticket + "张票");
                                ticket -= 1;
                                
                                try {
                                        Thread.sleep(100);
                                } catch (InterruptedException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                }
                        } else {
                                System.out.println(Thread.currentThread().getName() +
                                 "售罄!!!");
                                break;
                        }
                }
        }
}

public class Demo1 {
        public static void main(String[] args) {
                Thread thread = new Thread(new SingleThread(),"淘票票");
                Thread thread2 = new Thread(new SingleThread(),"猫眼");
                Thread thread3 = new Thread(new SingleThread(),"美团");
                
                thread.start();
                thread2.start();
                thread3.start();
        }
}



从上面的例子上可以看到,最后一张票被每一个平台都卖了一次,这样子肯定是不符合实际情况的,这就是本次我们需要解决的问题。

2. 解决方法:2.1 同步代码块  1.格式:
[Java] 纯文本查看 复制代码
synchronized ("锁") {[/b][b]//需要同步的代码[/b][/size][list=1]
[*][size=2]}


2.特征:
a: synchronized关键字后面的小括号里面的对象是锁对象,并且要求如果是多线程的情况下,锁对象必须是唯一的。
b: synchronized后大括号中的代码就是需要同步的代码,或者说加锁的代码,大括号里面的内容一次有且只允许一个线程类对象进入执行的操作,其余的线程类对象需要等待该线程类对象开锁才能进入。
c: 同步代码块中的代码越短越好,在保证足够安全的情况下,提高性能。

[Java] 纯文本查看 复制代码
// 1. 使用同步代码块解决多线程中共享资源冲突的问题
 
/**
 * 自定义售票线程类
 * 
 * @author 
 *
 */
//同步代码块
class SingleThread1 implements Runnable {

        // 共享资源,100张票
        private static int ticket = 100;

        @Override
        public void run() {
                while (true) {
                        synchronized ("锁") {

                                if (ticket > 0) {
                                        System.out.println(Thread.currentThread().getName() +
                                         "售出了第" + ticket + "张票");
                                        ticket -= 1;

                                        try {
                                                Thread.sleep(100);
                                        } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                        }
                                } else {
                                        System.out.println(Thread.currentThread().getName() +
                                         "售罄!!!");
                                        break;
                                }
                        }
                }
        }
}

public class Demo2 {
        public static void main(String[] args) {
                Thread thread = new Thread(new SingleThread1(), "淘票票");
                Thread thread2 = new Thread(new SingleThread1(), "猫眼");
                Thread thread3 = new Thread(new SingleThread1(), "美团");

                thread.start();
                thread2.start();
                thread3.start();
        }
}

2.2 同步方法
什么是同步方法:使用synchronized关键字修饰的方法就是同步方法,同步方法一次有且只允许一个线程类对象进入执行操作。
2.2.1 静态同步方法
静态方法使用synchronized关键字修饰就是静态同步方法,静态同步方法的锁对象是当前类对应的字节码文件,是唯一的。
如果是选择静态同步方法的话,因为锁对象是.class字节码文件,具有唯一性,多个线程使用的锁是同一个。

[Java] 纯文本查看 复制代码
// 2.1 使用静态成员方法解决多线程中共享资源冲突的问题
/**
 * 自定义售票线程类
 * 
 * @author 
 *
 */
//同步方法
class SingleThread3 implements Runnable {

        // 共享资源,100张票
        private static int ticket = 100;

        @Override
        public void run() {
                while (true) {
                        sellTicket();
                        if(ticket <= 0) {
                                break;
                        }
                }
        }

        // 静态同步方法
        public static synchronized void sellTicket() {
                if (ticket > 0) {
                        System.out.println(Thread.currentThread().getName() +
                         "售出了第" + ticket + "张票");
                        ticket -= 1;

                        try {
                                Thread.sleep(100);
                        } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                } else {
                        System.out.println(Thread.currentThread().getName() + "售罄!!!");
                }
        }
}

public class Demo3 {
        public static void main(String[] args) {
        //使用静态同步方法
                Thread thread1 = new Thread(new SingleThread3(), "淘票票");
                Thread thread2 = new Thread(new SingleThread3(), "猫眼");
                Thread thread3 = new Thread(new SingleThread3(), "美团");

                thread1.start();
                thread2.start();
                thread3.start();
        }
}

2.2.2 非静态同步方法
  • 非静态方法使用synchronized关键字修饰的就是非静态同步方法,非静态同步方法的锁对象是当前类对象 - this。
  • 如果是非静态同步方法的话,需要保证执行的线程类对象目标代码只有一个,因为锁对象为当前类对象。
[Java] 纯文本查看 复制代码
// 2.2 使用静态成员方法解决多线程中共享资源冲突的问题[/size]
[size=16px]/**[/size]
[size=16px] * 自定义售票线程类[/size]
[size=16px] * [/size]
[size=16px] * @author [/size]
[size=16px] *[/size]
[size=16px] */[/size]
[size=16px]//同步方法[/size]
[size=16px]class SingleThread3 implements Runnable {[/size]

[size=16px]        // 共享资源,100张票[/size]
[size=16px]        private static int ticket = 100;[/size]

[size=16px]        @Override[/size]
[size=16px]        public void run() {[/size]
[size=16px]                while (true) {[/size]
[size=16px]                        sellTicket();[/size]
[size=16px]                        if(ticket <= 0) {[/size]
[size=16px]                                break;[/size]
[size=16px]                        }[/size]
[size=16px]                }[/size]
[size=16px]        }[/size]
[size=16px]        [/size]
[size=16px]        //非静态同步方法[/size]
[size=16px]        public synchronized void sellTicket() {[/size]
[size=16px]                if (ticket > 0) {[/size]
[size=16px]                        System.out.println(Thread.currentThread().getName() +[/size]
[size=16px]                         "售出了第" + ticket + "张票");[/size]
[size=16px]                        ticket -= 1;[/size]

[size=16px]                        try {[/size]
[size=16px]                                Thread.sleep(100);[/size]
[size=16px]                        } catch (InterruptedException e) {[/size]
[size=16px]                                // TODO Auto-generated catch block[/size]
[size=16px]                                e.printStackTrace();[/size]
[size=16px]                        }[/size]
[size=16px]                } else {[/size]
[size=16px]                        System.out.println(Thread.currentThread().getName() +[/size]
[size=16px]                         "售罄!!!");[/size]
[size=16px]                }[/size]
[size=16px]        }[/size]

[size=16px]}[/size]

[size=16px]public class Demo3 {[/size]
[size=16px]        public static void main(String[] args) {[/size]
[size=16px]                //使用非静态同步方法[/size]
[size=16px]                //使用同一个目标代码对象[/size]
[size=16px]                SingleThread3 singleThread3 = new SingleThread3();[/size]
[size=16px]                Thread thread1 = new Thread(singleThread3,"淘票票");[/size]
[size=16px]                Thread thread2 = new Thread(singleThread3,"猫眼");[/size]
[size=16px]                Thread thread3 = new Thread(singleThread3,"美团");[/size]
[size=16px]        }[/size]
[size=16px]}[/size]
[size=16px]

2.3 Lock锁
  • 对象化操作:Lock lock = new ReentramtLock( );
  • 加锁:lock.lock( );
  • 开锁:lock.unlock( );
    [Java] 纯文本查看 复制代码
    // 使用静态Lock锁解决共享资源冲突的问题[/size]
    /**
     * 自定义售票线程类
     * 
     * @author 
     *
     */
    //lock加锁操作
    class SingleThread4 implements Runnable {
    
            // 共享资源,100张票
            private static int ticket = 100;
            
            //创建锁对象,这里使用的是静态的方式,锁对象是唯一的
            static Lock lock = new ReentrantLock();
    
            @Override
            public void run() {
                    while (true) {
                                    
                            //加锁
                            lock.lock();
                                    if (ticket > 0) {
                                            System.out.println(Thread.currentThread().getName() +
                                             "售出了第" + ticket + "张票");
                                            ticket -= 1;
    
                                            try {
                                                    Thread.sleep(100);
                                            } catch (InterruptedException e) {
                                                    // TODO Auto-generated catch block
                                                    e.printStackTrace();
                                            }
                                    } else {
                                            System.out.println(Thread.currentThread().getName() +
                                             "售罄!!!");
                                            break;
                                    }
                            lock.unlock();
                    }
            }
    }
    
    public class Demo4 {
            public static void main(String[] args) {
                    Thread thread = new Thread(new SingleThread4(), "淘票票");
                    Thread thread2 = new Thread(new SingleThread4(), "猫眼");
                    Thread thread3 = new Thread(new SingleThread4(), "美团");
    
                    thread.start();
                    thread2.start();
                    thread3.start();
            }
    }
    







166 个回复

正序浏览

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报
耙丫丫 发表于 2020-3-27 16:23
6666666666666666666666666

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报

努力,加油哦~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马