多线程的共享与同步

    xiaoxiao2026-05-26  5

    当用多线程来实现四个窗口共同卖票问题时,要共享同一个变量,我们用继承Runnable接口的方式来创建线程。

    /* 四个窗口同时卖票 因为是同时,所以使用多线程 创建4个线程,都是卖票 因为都是卖票,说明4个线程的任务是一样的 只需要定义一个类继承Thread 对于此种方法的线程,线程和线程任务是绑定在一起的。 而需要公用一个变量时,我们需要设置静态变量。 为了解决四个线程共享票的问题,需要使用创建线程的第二种方式: 1:创建实现了Runnable接口的子类 2:重写Runnable接口中的run方法 3:创建实现了Runnable接口的子类的对象 4:创建Thread类的对象,也就是在创建线程 5: 把实现了Runnable接口的子类对象作为参数传递给Thread类的构造方法 把线程任务进行了描述,也就是面向对象, 线程任务和线程对象的分离,线程执行什么任务不再重要,只要是实现了Runnable接口的子类对象都可以作为 参数传递给Thread的构造方法 实现接口的同时还可以继承父类 */ 对于实现的接口,实际上是为线程存储执行任务的。 //这是一个描述线程任务的类 class Ticket implements Runnable { private int num = 50; public void run() { while(true) { if(num>0) { //在这里的时候,当num==1的时候,该线程进入,然后又交出cpu,num还没有--, //可能在其他线程变为0,因此再执行该线程时,num又--,导致出现输出负数,因此又引出锁来避免 try{Thread.sleep(20);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"...sale..."+num--); } } } } class Demo2 { public static void main(String[] args) { Ticket t = new Ticket(); //这里相当于把线程任务交给线程 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(); } }

    为什么创建线程的第二种方式可以解决卖票问题?

    第一种创建线程的方式:线程和线程任务是绑定在一起的,创建4个线程就创建了4份资源 第二种创建线程的方式: 线程和线程任务进行了分离,只需要创建一个任务,让4个线程分别去执行

    刚刚说道,程序的运行可能出现不合法的小于0的数

    程序出现了安全问题: 出现了0,-1,-2的票 出现问题的原因: 1:多个线程操作了相同的数据 2:操作共享数据的语句有多条,一个线程得到cpu,执行了多条语句的一部分时,还没有全部执行完 就被抢走了cpu,当线程再次得到cpu时,直接执行后边的语句导致问题 解决问题的办法:一个线程得到cpu,执行了多条语句的一部分时,其它线程不能抢走cpu,只有当该线程把所有操作共享数据的语句全部执行完时,其它线程才能抢走cpu java提供的解决问题的方式:同步代码块 synchronized(对象) { 操作共享数据的语句 } 使用同步代码块,线程每次都要判断锁,降低了程序性能 使用同步需要满足的条件: 1:至少有两个线程 2:多个线程使用同一把锁 */ //因此我们修改代码,如下,加锁 synchronized(obj)//获取锁 实现了排斥其它线程 监视器,锁旗标,锁 t1 t2 t3 t4 { if(num>0)//0 { //强制线程放弃cpu,睡眠的线程不会放弃锁 try{Thread.sleep(20);}catch(InterruptedException e){e.printStackTrace();} System.out.println(Thread.currentThread().getName()+"...sale..."+num--);//1 } }//释放锁

    下面我们用第一种方式加锁解决该问题,肯能你会问了,为什么加了锁还会出现非法数据的情况

    class Ticket extends Thread { private static int num = 50; //St st = St.getInstance(); Object obj = new Object(); public void run() { while(true) { synchronized(obj) { if(num>0) { try{Thread.sleep(20);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"...sale..."+num--); } } } } } class practice2 { public static void main(String[] args) { Ticket t1 = new Ticket(); Ticket t2 = new Ticket(); Ticket t3 = new Ticket(); Ticket t4 = new Ticket(); t1.start(); t2.start(); t3.start(); t4.start(); } }

    其实问题很简单,我们只不过是用了四个锁,锁不唯一,并没有发挥应有的作用,我们可以构建个单例对象,传给线程用。

    class St { private static St st = new St(); private St(){} public static St getInstance(){ return st; } }

    还有就是我们的锁可以放在函数上,那么我们这个函数就是同步函数

    //当函数中的代码全部放在了同步代码块中,那么这个函数就是同步函数 public synchronized void add(double money)//同步函数 { sum = sum+money; System.out.println("sum="+sum); }
    转载请注明原文地址: https://ju.6miu.com/read-1310081.html
    最新回复(0)