• synchronized站点抢票同步例题



    多线程环境安全问题的判断标准(一定要三个同时满足)
    是否是多线程环境
    是否有共享数据

    是否有多条语句操作(修改)共享数据

    为什么出问题:
    CPU的一次操作必须是原子性的,在一个时间点,CPU只能执行一条指令,而一条语句是由多条指令组成的,比如说i++指令,CPU要先执行i+1,然后将i+1的值赋给i,然后再输出。我们用一条语句来理解,比如下面的卖票程序,当A站点输出语句“A站点还剩88张票”,这个时候还没执行到i--语句,这是B站点抢占到CPU,因为i--还没有执行,B站点也会输出“B站点还剩88张票”,这就出现了线程安全问题。

    线程方法:

    public final int getPriority()  回去当前线程名
    public final void setPriority(int newPriority)  设定当前线程名

    public static void sleep(long millis) 线程休眠

    public final void join() 线程加入  意思是加入的线程优先运行,运行结束后才会轮到下一个线程   注意:必须先开启该线程才能加入线程

    public static void yield()  线程礼让 目的时尚线程抢占更加均衡

    public final void setDaemon(boolean on)  后台线程:守护线程,精灵线程

    public final void stop():中断线程  不建议使用
    public void interrupt(): 中断线程

     如何正确地停止一个线程?

    A:①、使用退出标志,使线程正常退出,也就是当 run 方法完成后线程终止;
    ②、使用 interrupt 方法中断线程
    ③、使用 stop 方法强行终止,但是不推荐使用,因为 stop 和 suspend 以及 resume 一样存在死锁威胁,并且都是过期作废的方法。

    第一种,继承Thread创建多线程,同步方法,静态锁obj对象,使用同步代码块。  

    两者不同点红色标注

    public class MyThread extends Thread{
        static int i=100 ;
        static Object obj=new Object();
        
        public MyThread() {
            super();
        }
        public MyThread(String name) {    
            super(name);
        }
    
        @Override
        public void run() {
            while(i>0){
                synchronized (obj) {//obj对象必须静态,否则两个对象调用的obj不相同,必须保证只有一把锁
                    System.out.println(Thread.currentThread().getName()+"抢到票,还剩"+i+"张票");
                    i--;
                }
            }
        }
    }
    
    public class ThreadTest {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread("A站点");
        MyThread thread2 = new MyThread("B站点");
        thread1.start();
        thread2.start();
    }
    }
    执行结果
    B站点抢到票,还剩100张票
    A站点抢到票,还剩99张票
    A站点抢到票,还剩98张票
    A站点抢到票,还剩97张票
    A站点抢到票,还剩96张票
    A站点抢到票,还剩95张票
    A站点抢到票,还剩94张票
    A站点抢到票,还剩93张票
    A站点抢到票,还剩92张票
    A站点抢到票,还剩91张票
    A站点抢到票,还剩90张票
    A站点抢到票,还剩89张票
    A站点抢到票,还剩88张票
    A站点抢到票,还剩87张票
    A站点抢到票,还剩86张票
    A站点抢到票,还剩85张票
    A站点抢到票,还剩84张票
    A站点抢到票,还剩83张票
    A站点抢到票,还剩82张票

    第二种 实现runnable接口

     1 public class MyRunnable implements Runnable {
     2     int i=100;
     3     Object obj =new Object();
     4     @Override
     5     public void run() {
     6         while(i>0) {
     7              //因为线程虽然有两个 但是多态得到的子类对象只有一个 所以不用静态obj 
     8             //在这里使用代码块而不使用同步关键字修饰方法是因为同步方法,那一个对象会把这个方法执行完才会跳出循环,那就没票了
     9             //使用obj和this是一个意思
    10             synchronized(this) { 
    11                 System.out.println(Thread.currentThread().getName()+"抢到票,还剩"+i+"张票");
    12                 i--;
    13                 try {
    14                     Thread.sleep(100);//加个休眠模拟网络延迟,不知道为什么不加休眠一个线程能抢光所有的票
    15                 } catch (InterruptedException e) {
    16                     // TODO Auto-generated catch block
    17                     e.printStackTrace();
    18                 }
    19             }
    20         }
    21     }
    22 }
    23 
    24 public static void main(String[] args) {
    25     MyRunnable runnable =new MyRunnable();
    26     Thread thread1 = new Thread(runnable,"A站点");
    27     Thread thread2 = new Thread(runnable,"B站点");
    28     thread2.start();
    29     thread1.start();
    30 }
    31 }
  • 相关阅读:
    数组中的趣味题二
    数组中的趣味题一
    归并排序
    堆内存与栈内存
    c++中的继承和组合
    直接插入排序
    NYOJ 1067 Compress String(区间dp)
    C++ Primer 学习笔记与思考_7 void和void*指针的使用方法
    ucgui界面设计演示样例2
    手机无法连接电脑的手机助手
  • 原文地址:https://www.cnblogs.com/19322li/p/10698815.html
Copyright © 2020-2023  润新知