zoukankan      html  css  js  c++  java
  • 36.1 线程锁

    一、没用锁之前出现的问题

    package day34_thread_线程.线程锁;
    
    /*
     * t1,t2,t3
     * 假设只剩一张票
     * t1过来了,他一看有票,他就进来了,但是他突然肚子不舒服,然后他就去上卫生间了
     * t2也过来了,他一看也有票,他也进来了,但是他的肚子也不舒服,他也去上卫生间了
     *
     * t1上完了卫生间回来了,开始售票
     *     tickets = 0;
     * t2也上完卫生间回来了,他也进行售票
     *  tickets = -1;
     *
     *
     */
    
    public class SleepThread implements Runnable {
        int nums = 20;
    
        @Override
        public void run() {
    //        if(num > 0) {
    //            for(int i=0;i<100;i++) {
    //                System.out.println(Thread.currentThread().getName() + ":" + i);
    //            }
            while(true) {
                if(nums > 0) {
                    try {
                        Thread.sleep(100);
                } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                    System.out.println(Thread.currentThread().getName() + ":" + nums--);
                }else {
                    System.exit(0);
                }
            }
        }
    }
    package day34_thread_线程.线程锁;
    /*
     * 模拟火车站售票
     *
     *        分析:
     *                首相需要有火车票的总数量,每售出一张则数量减一
     *                当火车票的数量小于1的时候,停止售票
     *                使用多线程模拟多个窗口进行售票
     *                当火车票全部售完,火车站也一样敞开大门欢迎我们
     *
     *        static void sleep(long millis) : 让当前线程睡一会
     */
    public class SleepDemo {
        public static void main(String[] args) {
            SleepThread st = new SleepThread();
            Thread t = new Thread(st);
            t.setName("窗口1");
            t.start();
    
            Thread t1 = new Thread(st);
            t1.setName("窗口2");
            t1.start();
    
            Thread t2 = new Thread(st);
            t2.setName("窗口3");
            t2.start();
    
        }
    }

    输出:会出现票的争夺,

    二、使用线程锁解决

    synchronized是java中的一个关键字,修饰符。
    synchronized:同步(锁),可以修饰代码块和方法,被修饰的代码块和方法一旦被某个线程访问,则直接锁住,其他的线程将无法访问

    同步代码块:
      synchronized(锁对象){
         }

    同步方法:
      public synchronized void method() {
        }

    synchronized代码块又分为这么几种:synchronized(this),synchronized(className.class)和synchronized(Object obj)

    * synchronized(this):修饰非静态方法,锁都在当前对象,只限制当前对象对该代码块的同步。

    * synchronized(className.class 字节码对象):修饰静态方法,锁在类而不在类对象,只要是className类对象访问该代码块都被要求同步。

    * synchronized(Object obj) :这时锁就是对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁

    1. 代码块

    package day34_thread_线程.线程锁;
    
    public class SynchronizedThtread implements Runnable {
        //火车票数 20
        int num = 20;
        Object obj = new Object();
    
        @Override
        public void run() {
    
            while(true) {
    
                synchronized(obj) {
                    try{Thread.sleep(100);
                    }catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(num > 0) {
                        System.out.println(Thread.currentThread().getName() + ":" + num--);
                    }
                }
    
            }
        }
    }
     
    public class SynDemo {
        public static void main(String[] args) {
            SynchronizedThtread st = new SynchronizedThtread();
    
            Thread t = new Thread(st);
            t.setName("窗口1");
            t.start();
    
            Thread t1 = new Thread(st);
            t1.setName("窗口2");
            t1.start();
    
            Thread t2 = new Thread(st);
            t2.setName("窗口3");
            t2.start();
        }
    }

    输出:

    线程切换,但是票数按顺序减少,符合要求

    2.静态方法、非静态方法

    package day34_thread_线程.线程锁;
    
    public class SynFunThread implements Runnable {
        /*static int num = 100;*/
        int num = 20;
    
        @Override
        public void run() {
            method();
        }
    
        private synchronized void method() {
            while(true) {
                if(num > 0) {
                    try{Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                    System.out.println(Thread.currentThread().getName() + ":" + num--);
                }
            }
        }
    
      /*  private static synchronized void method() {
            while(true) {
                if(num > 0) {
                    try{Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
    
                    System.out.println(Thread.currentThread().getName() + ":" + num--);
                }
            }
        }*/
    }
    public class SynFunDemo {
        public static void main(String[] args) {
            SynFunThread sft = new SynFunThread();
    
            Thread t = new Thread(sft);
            Thread t1 = new Thread(sft);
            Thread t2 = new Thread(sft);
    
            t.start();
            t1.start();
            t2.start();
        }
    }

    输出:

  • 相关阅读:
    转:验证日期的正则表达式比较全面地验证
    IIS应用地址池监控
    Net预编译 真的好用与否
    关键字检索,找到所有数据
    vue 文件上传自定义实现
    docker 基础(一)
    input表单中嵌入百度地图
    linux系统光盘开机自动挂载-配置本地yum源
    linux学习笔记基础篇(一)
    构建apache web 服务器
  • 原文地址:https://www.cnblogs.com/longesang/p/11340919.html
Copyright © 2011-2022 走看看