美文网首页
关于多线程的一些知识点(二)——临界资源

关于多线程的一些知识点(二)——临界资源

作者: li_荔枝 | 来源:发表于2019-10-20 22:49 被阅读0次

临界资源问题

先看例子

public class SourceConflict {

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (TicketCenter.currnetTicket > 0) {
                    System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
                }
            }
        };
        
        Thread t1 = new Thread(runnable, "t1");
        Thread t2 = new Thread(runnable, "t2");
        Thread t3 = new Thread(runnable, "t3");
        Thread t4 = new Thread(runnable, "t4");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    
    
}

class TicketCenter{
    public static int currnetTicket = 100;
}

运行程序,四个线程共享ticket资源,会同时操作票资源,不做处理会出现下面的问题


image.png

解决方法一:同步代码段

public class SynchronizedDemo {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (TicketCenter.currnetTicket > 0) {
                    //对象锁
                    synchronized ("") {
                        System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
                    }
                }
            }
        };
        
        Thread t1 = new Thread(runnable, "t1");
        Thread t2 = new Thread(runnable, "t2");
        Thread t3 = new Thread(runnable, "t3");
        Thread t4 = new Thread(runnable, "t4");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
}

上面的 //对象锁 synchronized ("") 可替换成
//类锁 synchronized(SynchronizedDemo.class)
只要保证四个线程看到的是同一所即可,
synchronized(new SynchronizedDemo())会报错,因为每次都会生成不同对象

好接下来我们看运行代码结果(我们的结果不一定相同)


image.png

但是!!!!!!!!


image.png

这是因为t2卖票时,t1,t3,t4拿到资源在锁外等待,线程切换的时候,他们看到的票数还是>0的,当t2卖出最后一张,票数为0,t1,t3,t4再做卖票动作时,会产生负数。

修改成这样就好了

synchronized ("") {
                        if (TicketCenter.currnetTicket == 0) {
                            return;
                        }
                        System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
                    }

解决方法二:同步方法

public class SynchronizedFunction {

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                while (TicketCenter.currnetTicket > 0) {
                    sell();
                }
            }
        };
        
        Thread t1 = new Thread(runnable, "t1");
        Thread t2 = new Thread(runnable, "t2");
        Thread t3 = new Thread(runnable, "t3");
        Thread t4 = new Thread(runnable, "t4");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
    
    /*同步方法
    静态方法:同步锁就是类锁, 当前类.class
    非静态方法: 同步锁是 this*/
    public synchronized static void sell(){
        if (TicketCenter.currnetTicket == 0) {
            return;
        }
        System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
    }
}

看结果


image.png

当需要同步的逻辑比较复杂的时候可以将他们放在方法里

解决方法三:显示锁

public class LockDemo {
public static void main(String[] args) {

    final ReentrantLock lock = new ReentrantLock();
    
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            while (TicketCenter.currnetTicket > 0) {
                //对临界资源加上显示锁
                lock.lock();
                if (TicketCenter.currnetTicket <= 0) {
                    return;
                }
                
                System.out.println(Thread.currentThread().getName()+"卖出一张票,剩余"+ --TicketCenter.currnetTicket);
                //对临界资源释放锁
                lock.unlock();
            }
        }
    };
    
    Thread t1 = new Thread(runnable, "t1");
    Thread t2 = new Thread(runnable, "t2");
    Thread t3 = new Thread(runnable, "t3");
    Thread t4 = new Thread(runnable, "t4");
    
    t1.start();
    t2.start();
    t3.start();
    t4.start();
}

}
结果没有问题,但是。。。
运行之后程序没有停止,有大佬可以告诉我为什么吗?

相关文章

  • 关于多线程的一些知识点(二)——临界资源

    临界资源问题 先看例子 运行程序,四个线程共享ticket资源,会同时操作票资源,不做处理会出现下面的问题 解决方...

  • Java 线程同步

    1. 多线程安全问题 当多线程并发访问临界资源时,如果破坏原子操作,可能会造成数据不一致 临界资源:共享资源(同一...

  • 开发十年,留下最完整的Java架构学习路线,学完年薪65W

    10. 解决临界资源问题之同步方法 11. 解决临界资源问题之ReentrantLock 12. 多线程讲解和理解...

  • JAVA知识梳理

    多线程相关 死锁 死锁四个条件: 互斥条件临界资源只能被一个线程拥有 占有且等待线程/进程拥有补发临界资源,但同时...

  • iOS多线程实现方案之 -- GCD

    昨天通过多线程实现方案之 -- NSThread说了关于 NSThread 多线程的一些知识点和用法, 其实之...

  • 并发编程(四):线程安全解决方案-synchronized

    临界区 一段代码内如果存在对共享资源的多线程多写操作,称这段代码为临界区。 竞态条件 多个线程在临界区内执行,由于...

  • synchronized与volatile的区别

    synchronized介绍: 在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操...

  • 多线程锁原理

    多线程锁原理 临界区: 在临界区内,会对共享资源进行访问和修改 共享资源: 在同一时间只能被单个线程所持有 访问临...

  • Objective-C中锁的几种实现方式

    锁的意义就是为了防止在多线程(多任务)的情况下对共享资源(临界资源)的脏读或者脏写。也可以理解为:用于执行多线程操...

  • Java基础之synchronized关键字

    一、概述 在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原...

网友评论

      本文标题:关于多线程的一些知识点(二)——临界资源

      本文链接:https://www.haomeiwen.com/subject/wrzamctx.html