栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

在Java中通过同步机制解决线程的安全问题(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Java中通过同步机制解决线程的安全问题(一)

使用同步代码块来解决线程安全问题
 
 synchronized(同步监视器){
     //需要被同步的代码
   }

例子:创建三个窗口卖票,总票数为100张

1.问题:买票的过程中出现了重票和错票 --- >出现了线程安全问题
2.问题出现的原因:当某个线程操作车票的过程中,尚未完成操作时,其他线程参与进来,也操作车票。
3.如何解决:当一个线程a在操作ticket时,其他线程不能参与进来,直到线程a操作完成时,其他线程才可以参与进来,这种情况即使线程a阻塞也不能被改变。

 方式一:继承Thread类的方式: 

public class WindowTest2 {
    public static void main(String[] args) {
        Window1 t1 = new Window1();
        Window1 t2 = new Window1();
        Window1 t3 = new Window1();

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

class Window1 extends Thread{
    private static int ticket=100;
    static Object obj=new Object();
    @Override
    public void run() {
        while (true) {
            synchronized (Window1.class) {//此处不能使用this,此时的this代表着t1,t2,t3,但可以使用Window1.class  Class clazz=Window1.class只加载一次
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(getName() + ",卖票,票号为" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }
        }
    }
}

 方式二:实现Runnable接口的方式:

public class WindowTest1 {
    public static void main(String[] args) {
        Window1 w = new Window1();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();


    }
}
class Window implements Runnable {
    private int ticket = 100;
//    Object obj = new Object();
    @Override
    public void run() {
        while (true) {
            synchronized(this){//此时的this表示唯一的Window的对象
                if (ticket > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票,票号为" + ticket);
                    ticket--;
                } else {
                    break;
                }
            }

        }
    }
}


  说明:

 1.操作共享数据的代码,即为需要被同步的代码。  -->不能包含代码多了,也不能包含代码少了。
 2.共享数据:多个线程共同操作的变量。比如:ticket就是共享数据。
 3.同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
     要求:多个线程必须要共用同一把锁。

补充:

  1. 在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。
  2. 在继承Thread类创建多线程的方式中,慎用this充当同步监视器,考虑使用当前类充当同步监视器。

两种方式的对比:
 开发中:优先选择:实现Runnable接口的方式
  原因:1. 实现的方式没类的单继承性的局限性
            2. 实现的方式更适合来处理多个线程共享数据的情况。

 联系:public class Thread implements Runnable
 相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中。
          目前两种方式,要想启动线程,都是调用的Thread类中的start()。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/860199.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号