文档章节

Java并发编程初级篇(十一):synchronized同步代码块

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/24 11:49
字数 727
阅读 78
收藏 0

#程序员薪资揭榜#你做程序员几年了?月薪多少?发量还在么?>>>

上一节我们讲解了synchronized方法,它能够保证多个线程并发访问同一个方法的时候,只有一个线程可以访问,其他线程被挂起直到上一个线程执行同步方法完毕。

使用synchronized修饰的方法确实保证了此方法的同步控制,但是这也只是公共变量只在在一个同步方法中被修改才没有问题。当有两个或者以上的方法会修改同一个公共变量的时候,synchronized方法就没有办法保证数据的一致性了,因为其他线程还可以调用两一个方法来修改这个公共变量的值。

所以我们需要使用一个控制类来保证公共变量在多个方法中被访问时只有一个线程能够修改它的值,其他线程都必须挂起等待这个线程的执行完毕。

synchronized (control) {
  doSomething...
}

示例代码:

我们用一个模拟电影院买票的例子,电影院有两部电影,这个电影院有多个售票窗口,每个窗口都可以销售任何一部电影的票,也可以受理任何一部电影的退票业务。

创建Cinema类模拟电影院,在这里我们有两部电影,针对这两部电影有各自独立的售票和退票方法,然后分别使用controlCinema1,controlCinema2来控制这两部电影的售票,退票方法的同步。来保证针对同一部电影在同一时间只有一个线程可以实现售票或者退票操作。

public class Cinema {
    private long vacanciesCinema1;
    private long vacanciesCinema2;
    private final Object controlCinema1, controlCinema2;

    public Cinema(long vacanciesCinema2, long vacanciesCinema1) {
        controlCinema1 = new Object();
        controlCinema2 = new Object();
        this.vacanciesCinema2 = vacanciesCinema2;
        this.vacanciesCinema1 = vacanciesCinema1;
    }

    public boolean sellTickets1(int number) {
        synchronized (controlCinema1) {
            if (vacanciesCinema1 >= number) {
                vacanciesCinema1 -= number;
                return true;
            } else {
                return false;
            }
        }
    }

    public boolean sellTickets2(int number) {
        synchronized (controlCinema2) {
            if (vacanciesCinema2 >= number) {
                vacanciesCinema2 -= number;
                return true;
            } else {
                return false;
            }
        }
    }

    public boolean returnTickets1(int number) {
        synchronized (controlCinema1) {
            vacanciesCinema1 += number;
            return true;
        }
    }

    public boolean returnTickets2(int number) {
        synchronized (controlCinema2) {
            vacanciesCinema2 += number;
            return true;
        }
    }

    public long getVacanciesCinema1() {
        return vacanciesCinema1;
    }

    public long getVacanciesCinema2() {
        return vacanciesCinema2;
    }
}

然后分别模拟两个售票窗口,处理若干售票,退票操作。

public class TicketOffice1 implements Runnable{
    private Cinema cinema;

    public TicketOffice1(Cinema cinema) {
        this.cinema = cinema;
    }

    @Override
    public void run() {
        cinema.sellTickets1(3);
        cinema.sellTickets1(2);
        cinema.sellTickets2(2);
        cinema.returnTickets1(3);
        cinema.sellTickets1(5);
        cinema.sellTickets2(2);
        cinema.sellTickets2(2);
        cinema.sellTickets2(2);
    }
}
public class TicketOffice2 implements Runnable{
    private Cinema cinema;

    public TicketOffice2(Cinema cinema) {
        this.cinema = cinema;
    }

    @Override
    public void run() {
        cinema.sellTickets2(2);
        cinema.sellTickets2(4);
        cinema.sellTickets1(2);
        cinema.sellTickets1(1);
        cinema.returnTickets2(2);
        cinema.sellTickets1(3);
        cinema.sellTickets2(2);
        cinema.sellTickets1(2);
    }
}

在主方法类中我们创建这两个售票窗口的线程并启动他们,观察最后剩余票数。

public class Main {
    public static void main(String[] args) {
        Cinema cinema = new Cinema(20, 20);

        TicketOffice1 office1 = new TicketOffice1(cinema);
        TicketOffice2 office2 = new TicketOffice2(cinema);

        Thread thread1 = new Thread(office1, "Ticket-Office-1");
        Thread thread2 = new Thread(office2, "TIcket-Office-2");

        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.printf("Room1 vacancies: %d\n", cinema.getVacanciesCinema1());
        System.out.printf("Room2 vacancies: %d\n", cinema.getVacanciesCinema2());
    }
}

查看控制台:

Room1 vacancies: 5
Room2 vacancies: 6

 

© 著作权归作者所有

阿拉德大陆的魔法师
粉丝 27
博文 91
码字总数 83019
作品 0
西城
程序员
私信 提问
加载中

评论(0)

synchronized关键字简介 多线程中篇(十一)

前面说过,Java对象都有与之关联的一个内部锁和监视器 内部锁是一种排它锁,能够保障原子性、可见性、有序性 从Java语言层面上说,内部锁使用synchronized关键字实现 synchronized可以修饰方...

osc_6bjpmnwf
2019/02/20
8
0
【原创】Java并发编程系列07 | synchronized原理

  20大进阶架构专题每日送达      并发编程中用到最多的关键字毫无疑问是synchronized。这篇文章就来探究下synchronized:   synchronized如何使用?   synchronized是实现同步加锁...

java进阶架构师
2019/11/13
0
0
关于Java里面多线程同步的一些知识

# 关于Java里面多线程同步的一些知识 对于任何Java开发者来说多线程和同步是一个非常重要的话题。比较好的掌握同步和线程安全相关的知识将使得我们则更加有优势,同时这些知识并不是非常容易...

欧阳海阳
2018/07/13
0
0
Java程序员从笨鸟到菜鸟之(十一)多线程讲解

本文来自:曹胜欢博客专栏。转载请注明出处:http://blog.csdn.net/csh624366188 多线程是java应用程序的一个特点,掌握java的多线程也是作为一java程序员必备的知识。多线程指的是在单个程序...

长平狐
2012/11/12
163
0
Java多线程学习(二)synchronized关键字(2)

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
2018/04/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Windows 10 中安装 Anaconda 3

首先通过下面链接地址下载 Anaconda 的个人版本。 https://www.anaconda.com/products/individual 从上面下载的地址中,选择你需要的版本,目前 Windows 应该基本上都是 64 位的了。 在你下载...

honeymoose
2分钟前
5
0
如何禁用textarea的resizable属性? - How do I disable the resizable property of a textarea?

问题: I want to disable the resizable property of a textarea . 我想禁用textarea的resizable属性。 Currently, I can resize a textarea by clicking on the bottom right corner of t......

技术盛宴
2分钟前
13
0
即时通信E聊SDK简介(1)

2.简介: E聊SDK是一套适用于PC端, 移动端的即时通讯解决方案,源代码开放。E聊整合了即时通讯的基础能力,使用E聊,您可以让您的应用快速接入即时聊天的功能。E聊现已适配PC Web, 移动Web, ...

E聊
14分钟前
7
0
多个知乎账号一起登陆,同时管理运营的神器!

随着互联网生态的优化,从2016年开始,信息内容产业相当有关注度,其和粉丝互动起来很方便、流量大到惊人、可长远发展等等优势,迅速聚集了无数企业和个人,为了有非常全面的播放数据,大家通...

易媒助手
18分钟前
22
0
403禁止vs 401未经授权的HTTP响应 - 403 Forbidden vs 401 Unauthorized HTTP responses

问题: For a web page that exists, but for which a user does not have sufficient privileges (they are not logged in or do not belong to the proper user group), what is the prope......

fyin1314
32分钟前
19
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部