精华内容
下载资源
问答
  • 如何解决多线程不安全比如买票,会出现一票多求,负票等问题解决; java提供了一个同步机制(同步锁):synchronized :包装其中的多条语句 例: synchronized(对象){ 多条语句对共享语句进行操作 } 对象:需要...

    如何解决多线程不安全

    比如买票,会出现一票多求,负票等问题
    
    解决;
        java提供了一个同步机制(同步锁):synchronized  :包装其中的多条语句
    
        例:
            synchronized(对象){
                 多条语句对共享语句进行操作
            }
            对象:需要使用同一个对象,封装到外面
        注意:任意对象,但必须创建,也必须存在
    

    线程安全的检测条件:
    1)看我们当前的环境是否属于多线程程序
    2)当前的多线程程序中是否有共享数据
    3)是否多条语句对共性数据进行操作

    需求:
    模拟电影院售票案例,现有100张票,三家影院同时出售,卖出每张票中间会有100毫秒的延迟

    代码:

    public class SellTickets implements Runnable {

    //定义票数
    private int tickets = 1;
    
    Demo d = new Demo();
    
    @Override
    public void run() {
        while(tickets<=100){
            //同步锁
            synchronized(d){
                if(tickets<=100){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":"+"正在出售第"+(tickets++)+"张票");
                }
            }
        }
    
    }
    

    }
    class Demo{}

    public static void main(String[] args) {
    SellTickets st = new SellTickets();

        //创建线程对象
        Thread th1 = new Thread(st, "窗口一");
        Thread th2 = new Thread(st, "窗口二");
        Thread th3 = new Thread(st, "窗口三");
    
        //启动线程
        th1.start();
        th2.start();
        th3.start();
    }
    

    结果:
    窗口一:正在出售第1张票
    窗口一:正在出售第2张票
    窗口一:正在出售第3张票
    窗口三:正在出售第4张票
    窗口三:正在出售第5张票
    窗口二:正在出售第6张票
    窗口二:正在出售第7张票
    窗口三:正在出售第8张票
    窗口三:正在出售第9张票
    窗口一:正在出售第10张票
    窗口一:正在出售第11张票
    窗口三:正在出售第12张票
    窗口二:正在出售第13张票
    窗口二:正在出售第14张票
    窗口三:正在出售第15张票
    窗口三:正在出售第16张票
    窗口一:正在出售第17张票
    窗口一:正在出售第18张票
    窗口一:正在出售第19张票
    窗口三:正在出售第20张票
    窗口三:正在出售第21张票
    窗口三:正在出售第22张票
    窗口三:正在出售第23张票
    窗口三:正在出售第24张票
    窗口三:正在出售第25张票
    窗口三:正在出售第26张票
    窗口三:正在出售第27张票
    窗口二:正在出售第28张票
    窗口二:正在出售第29张票
    窗口二:正在出售第30张票
    窗口三:正在出售第31张票
    窗口三:正在出售第32张票
    窗口三:正在出售第33张票
    窗口三:正在出售第34张票
    窗口一:正在出售第35张票
    窗口三:正在出售第36张票
    窗口二:正在出售第37张票
    窗口三:正在出售第38张票
    窗口三:正在出售第39张票
    窗口三:正在出售第40张票
    窗口三:正在出售第41张票
    窗口三:正在出售第42张票
    窗口一:正在出售第43张票
    窗口三:正在出售第44张票
    窗口三:正在出售第45张票
    窗口三:正在出售第46张票
    窗口三:正在出售第47张票
    窗口三:正在出售第48张票
    窗口三:正在出售第49张票
    窗口三:正在出售第50张票
    窗口二:正在出售第51张票
    窗口二:正在出售第52张票
    窗口二:正在出售第53张票
    窗口二:正在出售第54张票
    窗口二:正在出售第55张票
    窗口三:正在出售第56张票
    窗口一:正在出售第57张票
    窗口一:正在出售第58张票
    窗口三:正在出售第59张票
    窗口三:正在出售第60张票
    窗口三:正在出售第61张票
    窗口三:正在出售第62张票
    窗口三:正在出售第63张票
    窗口三:正在出售第64张票
    窗口三:正在出售第65张票
    窗口二:正在出售第66张票
    窗口三:正在出售第67张票
    窗口三:正在出售第68张票
    窗口三:正在出售第69张票
    窗口三:正在出售第70张票
    窗口三:正在出售第71张票
    窗口三:正在出售第72张票
    窗口三:正在出售第73张票
    窗口三:正在出售第74张票
    窗口一:正在出售第75张票
    窗口三:正在出售第76张票
    窗口三:正在出售第77张票
    窗口三:正在出售第78张票
    窗口三:正在出售第79张票
    窗口三:正在出售第80张票
    窗口二:正在出售第81张票
    窗口三:正在出售第82张票
    窗口一:正在出售第83张票
    窗口三:正在出售第84张票
    窗口三:正在出售第85张票
    窗口二:正在出售第86张票
    窗口二:正在出售第87张票
    窗口三:正在出售第88张票
    窗口三:正在出售第89张票
    窗口一:正在出售第90张票
    窗口一:正在出售第91张票
    窗口三:正在出售第92张票
    窗口三:正在出售第93张票
    窗口二:正在出售第94张票
    窗口三:正在出售第95张票
    窗口一:正在出售第96张票
    窗口一:正在出售第97张票
    窗口三:正在出售第98张票
    窗口二:正在出售第99张票
    窗口二:正在出售第100张票

    使用同步机制解决了线程的安全问题,但是我们并没有看到具体的锁对象是谁,JDK5以后java提供了接口Lock,里面又提供了一些方法:
    public void lock()获取锁
    public void unlock():释放锁

        Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作
        由于该Lock接口不能实例化,提供了子实现类:ReentrantLock
    

    代码:

    public class MyLock implements Runnable{
     private int tickets = 1;
     //创建锁对象
     Lock l = new ReentrantLock();
    
    @Override
    public void run() {
        while(tickets <= 100){
            l.lock();
            if(tickets<=100){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+":"+"正在出售第"+(tickets++)+"张票");
            }
            l.unlock();
        }
    
    }
    

    }

    public static void main(String[] args) {
    MyLock ml = new MyLock();

        //创建多线程对象
        Thread th1 = new Thread(ml, "窗口一");
        Thread th2 = new Thread(ml, "窗口二");
        Thread th3 = new Thread(ml, "窗口三");
    
        th1.start();
        th2.start();
        th3.start();
    }
    

    结果:
    窗口一:正在出售第1张票
    窗口二:正在出售第2张票
    窗口二:正在出售第3张票
    窗口二:正在出售第4张票
    窗口二:正在出售第5张票
    窗口二:正在出售第6张票
    窗口二:正在出售第7张票
    窗口二:正在出售第8张票
    窗口二:正在出售第9张票
    窗口二:正在出售第10张票
    窗口二:正在出售第11张票
    窗口三:正在出售第12张票
    窗口一:正在出售第13张票
    窗口二:正在出售第14张票
    窗口三:正在出售第15张票
    窗口一:正在出售第16张票
    窗口二:正在出售第17张票
    窗口二:正在出售第18张票
    窗口二:正在出售第19张票
    窗口三:正在出售第20张票
    窗口三:正在出售第21张票
    窗口三:正在出售第22张票
    窗口一:正在出售第23张票
    窗口二:正在出售第24张票
    窗口二:正在出售第25张票
    窗口二:正在出售第26张票
    窗口二:正在出售第27张票
    窗口二:正在出售第28张票
    窗口二:正在出售第29张票
    窗口二:正在出售第30张票
    窗口三:正在出售第31张票
    窗口三:正在出售第32张票
    窗口一:正在出售第33张票
    窗口二:正在出售第34张票
    窗口三:正在出售第35张票
    窗口一:正在出售第36张票
    窗口二:正在出售第37张票
    窗口二:正在出售第38张票
    窗口二:正在出售第39张票
    窗口二:正在出售第40张票
    窗口二:正在出售第41张票
    窗口二:正在出售第42张票
    窗口二:正在出售第43张票
    窗口二:正在出售第44张票
    窗口二:正在出售第45张票
    窗口二:正在出售第46张票
    窗口二:正在出售第47张票
    窗口三:正在出售第48张票
    窗口三:正在出售第49张票
    窗口三:正在出售第50张票
    窗口三:正在出售第51张票
    窗口三:正在出售第52张票
    窗口一:正在出售第53张票
    窗口二:正在出售第54张票
    窗口二:正在出售第55张票
    窗口二:正在出售第56张票
    窗口三:正在出售第57张票
    窗口三:正在出售第58张票
    窗口一:正在出售第59张票
    窗口二:正在出售第60张票
    窗口二:正在出售第61张票
    窗口二:正在出售第62张票
    窗口二:正在出售第63张票
    窗口二:正在出售第64张票
    窗口二:正在出售第65张票
    窗口二:正在出售第66张票
    窗口二:正在出售第67张票
    窗口二:正在出售第68张票
    窗口二:正在出售第69张票
    窗口二:正在出售第70张票
    窗口三:正在出售第71张票
    窗口一:正在出售第72张票
    窗口二:正在出售第73张票
    窗口二:正在出售第74张票
    窗口二:正在出售第75张票
    窗口二:正在出售第76张票
    窗口二:正在出售第77张票
    窗口二:正在出售第78张票
    窗口二:正在出售第79张票
    窗口二:正在出售第80张票
    窗口二:正在出售第81张票
    窗口二:正在出售第82张票
    窗口二:正在出售第83张票
    窗口二:正在出售第84张票
    窗口二:正在出售第85张票
    窗口二:正在出售第86张票
    窗口二:正在出售第87张票
    窗口二:正在出售第88张票
    窗口二:正在出售第89张票
    窗口二:正在出售第90张票
    窗口二:正在出售第91张票
    窗口二:正在出售第92张票
    窗口二:正在出售第93张票
    窗口二:正在出售第94张票
    窗口二:正在出售第95张票
    窗口二:正在出售第96张票
    窗口二:正在出售第97张票
    窗口三:正在出售第98张票
    窗口一:正在出售第99张票
    窗口二:正在出售第100张票

    展开全文
  • 此篇文章已证明了ArrayList为线程不安全的事实,如想了解请移步用一段程序证明ArrayList是线程不安全如何解决这个问题,个人所知有以下两种方式 集合工具类Collections加锁,代码如下,无报错运行 import java....

    该篇文章已证明了ArrayList为线程不安全的事实,如想了解请移步用一段程序证明ArrayList是线程不安全的
    如何解决这个问题,个人所知有以下两种方式

    1. 集合工具类Collections加锁,代码如下,无报错运行
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.UUID;
    /**
     * Description:验证arrayList为线程不安全的
     *
     * @author Mr Li
     * @date 2019/4/8
     **/
    public class TestArrayList {
        public static void main(String[] args) {
            //新建arrayList
            List<String> list = new ArrayList<>();
            //使用集合工具类加锁
            Collections.synchronizedList(list);
            //采用多线程的方式向list中添加随机数
            for (int i = 0; i < 40; i++) {
                new Thread(()->{
                    list.add(UUID.randomUUID().toString().substring(0,8));
                    System.out.println(Thread.currentThread().getName() + "/t" +list);
                },String.valueOf(i)).start();
            }
        }
    }
    
    
    1. 使用CopyOnWriteArrayList,代码如下,完美运行
    import java.util.List;
    import java.util.UUID;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    /**
     * Description:验证arrayList为线程不安全的
     *
     * @author Mr Li
     * @date 2019/4/8
     **/
    public class TestArrayList {
        public static void main(String[] args) {
            //新建arrayList,使用CopyOnWriteArrayList
            List<String> list = new CopyOnWriteArrayList<>();
            //采用多线程的方式向list中添加随机数
            for (int i = 0; i < 40; i++) {
                new Thread(()->{
                    list.add(UUID.randomUUID().toString().substring(0,8));
                    System.out.println(Thread.currentThread().getName() + "/t" +list);
                },String.valueOf(i)).start();
            }
        }
    }
    
    
    展开全文
  • 通过售票的例子通过分析:发现,打印出0,-1,-2等错票。多线程的运行出现了安全问题。问题的原因:当多条语句在...其他线程不可以参与执行java对于多线程安全问题提供了专业的解决方式。就是同步代码块。synchro...

    通过售票的例子

    通过分析:发现,打印出0,-1,-2等错票。

    多线程的运行出现了安全问题。

    问题的原因:

    当多条语句在操作同一个线程共享数据时。一个线程对多条语句只执行了一部分

    还没执行完。另一个线程参与进来执行。导致共享数据的错误。

    解决办法:

    对多条操作共享数据的语句。只能让一个线程都执行完。在执行过程中。

    其他线程不可以参与执行

    java对于多线程的安全问题提供了专业的解决方式。

    就是同步代码块。

    synchronized(对象)

    {

    需要被同步的代码

    }

    /*

    通过分析:发现,打印出0,-1,-2等错票。

    多线程的运行出现了安全问题。

    问题的原因:

    当多条语句在操作同一个线程共享数据时。一个线程对多条语句只执行了一部分

    还没执行完。另一个线程参与进来执行。导致共享数据的错误。

    解决办法:

    对多条操作共享数据的语句。只能让一个线程都执行完。在执行过程中。

    其他线程不可以参与执行

    java对于多线程的安全问题提供了专业的解决方式。

    就是同步代码块。

    synchronized(对象)

    {

    需要被同步的代码

    }

    */

    class Tickets implements Runnable

    {

    private int tick = 100;

    Object obj = new Object();

    public void run()

    {

    while(true)

    {

    synchronized(obj)

    {

    if(tick >0)

    {

    try

    {

    Thread.sleep(10);

    }

    catch (Exception e)

    {

    }

    System.out.println("tick:"+tick--);

    }

    }

    }

    }

    }

    class Test_11_08

    {

    public static void main(String[] args)

    {

    System.out.println("Hello Wolrd");

    Tickets t = new Tickets();

    Thread t1 = new Thread(t);

    Thread t2 = new Thread(t);

    Thread t3 = new Thread(t);

    Thread t4 = new Thread(t);

    t1.start();

    t2.start();

    t3.start();

    t4.start();

    }

    }

    展开全文
  • 使用多线程之间同步synchronized或使用锁(lock).因为多线程将可能会发生数据冲突问题(线程不安全...这样的话就可以解决线程不安全问题。而多线程同步之后,当多个线程共享同一个资源,不会受到其他线程的干扰。 ...

    使用多线程之间同步synchronized或使用锁(lock).因为多线程将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行。代码执行完成后释放锁,然后才能让线程进行执行。这样的话就可以解决线程不安全问题。而多线程同步之后,当多个线程共享同一个资源,不会受到其他线程的干扰。

    展开全文
  • 线程安全问题1,观察代码(存在线程安全问题)2,线程安全的概念3, 线程不安全的原因3.1 原子性3.2 可见性3.3 代码顺序性4 解决之前的线程不安全问题5, synchronized 关键字-监视器锁monitor lock6. volatile 关键...
  • 如何解决线程不安全

    2021-01-17 22:25:21
    一、什么是线程不安全 简单的解释则是:个线程抢占执行,则导致出现逻辑上的错误。 通过售票代码来解释这种不安全行为 public class Test { public static void main(String[] args) { //线程不安全示范 ...
  • 如何解决线程不安全? 1.线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。线程...
  • 那么本节就来讲讲,如何解决线程安全问题呢? 1、synchronized synchronized关键字,就是java用来控制线程同步的,比如上节的最后举例中,在代码中加入共享变量后,使用多线程调用时,会产生count数据产生偏差问题...
  • 线程不安全:就是不提供数据访问保护,有可能出现个线程先后更改数据造成所得到的数据是脏数据 为什么Lis是不安全的呢?show code ArrayList<String> list = new ArrayList<>(); for (int i = 0; i ...
  • 问:如何解决多线程之间线程安全问题? 答:使用多线程之间同步或使用锁(lock)。 问:为什么使用线程同步或使用锁能解决线程安全问题呢? 答:将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行...
  • 导致原因,ArrayList是线程不安全的,所以先多线程下可能会出现并发修改异常。 导致原因:多线程并发争抢同一个资源。 可以用Vector来解决线程安全问题。 但是Vector是重锁,性能太堪忧了。 用: ...
  • 解决线程不安全问题,首先要了解导致线程不安全的因素: CPU是抢占式执行的(万恶之源) 个线程同时修改同一个变量(即共享变量) 可见性 原子性 指令重排序 1、2两种因素,是我们无法改变的,所以我们只能...
  • 在单线程中不会出现线程安全问题,而在多线程编程中,有可能会出现同时访问同一个资源的情况,这种资源可以是各种类型的的资源:一个变量、一个对象、一个文件、一个数据库表等,而当多个线程同时访问同一个资源的...
  • ## 两种反射 推荐使用第二种 效率较高 Set<String> set = Collections.synchronizedSet(new HashSet<>()); Set<String> set = new CopyOnWriteArraySet<>...import java.
  • ArrayList线程不安全的表现 在个线程进行add操作时可能会导致elementData数组越界 一个线程的值覆盖另一个线程添加的值 List<Object> values = Collections.synchronizedList(new ArrayList<>()); ...
  • 什么是多线程安全问题?如何解决? 1,什么叫多线程安全问题? 当多个线程对同一全局变量进行写操作时,可能会发生数据冲突问题.这就是多线程安全问题. 进行读时不会发生安全问题. 经典案例: 多线程抢购火车票. 比如:现有...
  • 文章目录避免共享可变可重入代码线程封闭必须共享互斥同步非阻塞同步 ...线程安全就是多线程并发访问的时候,线程之间所共享的资源不会被污染或被破坏。 我们知道线程共享的内存区域主要就是java堆,而jav...
  • 也就说一个servlet只能生成一个对象,这样个线程操作一个实例对象,必然可能造成线程不安全。比如一个成员变量,其中一个线程改变他,还没有退出对该线程的访问。另外一个线程也进来了,也改变了这个成员变量,...
  • 原子操作:所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会...这样就不会出现线程不安全情况(案例中的购票系统出现负数的情况),这种原子操作思想还是挺有用的,在...
  •  在单线程中不会出现线程安全问题,而在多线程编程中,有可能会出现同时访问同一个资源的情况,这种资源可以是各种类型的的资源:一个变量、一个对象、一个文件、一个数据库表等,而当多个线程同时访问同一个资源的...
  • ArrayList 线程不安全多线程得环境下,线程会争抢资源,导致java.util.ConcurrentModificationException 并发修改异常 解决方法: Vector 将ArrayList 替换成为Vector 原理: *将指定的元素插入到此Vector的指定...
  • 上一篇讨论了如何解决线程安全的问题,... 类不是线程安全的原因主要就是它包含了一些属性,这些属性是这个类实例对象的变量,这些变量影响着对象状态,由于对这些属性的访问在多线程情况下出现一些不安全使得对象...
  • 1,如何保证线程安全 线程之间共享状态变量 将状态变量修改成可变的变量 在访问状态变量时使用同步 2,实现线程安全有那些方法 A:内置锁 Java代码 publicclasswidget{ publicsynch...
  • 上一篇讨论了如何解决线程安全的问题,... 类不是线程安全的原因主要就是它包含了一些属性,这些属性是这个类实例对象的变量,这些变量影响着对象状态,由于对这些属性的访问在多线程情况下出现一些不安全使得对象...
  • 从上节我们学到,当线程访问且更改同一个变量 时,很容易出现线程安全问题,诚然,我们可以通过一些其他手段,比如局部变量,个实例,调整程序结构来解决线程安全问题,但是通常来讲,通过同步机制 ...
  • i++;不是线程安全的。该语句执行过程如下,先把 i 的值取出来放到栈顶,可以理解为引入了一个第三方变量 k,此时,k的值为i,然后执行自增操作,i的...在Java语言中,++i和i++操作并线程安全的,在使用的时候,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 949
精华内容 379
关键字:

如何解决多线程不安全