线程同步基础之使用非依赖属性实现同步

当使用synchronized关键字来保护代码块时,必须把对象引用作为传入参数。通常情况下,使用this关键字来引用执行方法所属的对象,也可以使用其他的对象对其进行引用。一般来说,这些对象就是为这个目的而创建的。例如,在类中有两个非依赖属性,它们被多个线程共享,你必须同步每一个变量的访问,但是同一时刻只允许一个线程访问一个属性变量,其他某个线程访问另一个属性变量。

这里我们演示电影院售票场景。这个范例模拟了有两个屏幕和两个售票处的电影院。一个集票处卖出的一张票,只能用于其中一个屏幕,不能同时用于两个屏幕,因此每个电影院的剩余票数是独立的属性。

示例:

package concurrency;

public class Main9 {
    public static void main(String[] args) {
        Cinema cinema = new Cinema();
        TicketOffice1 ticketOffice1 = new TicketOffice1(cinema);
        Thread thread1 = new Thread(ticketOffice1,"TicketOffice1");
        TicketOffice2 ticketOffice2 = new TicketOffice2(cinema);
        Thread thread2 = new Thread(ticketOffice2,"TicketOffice2");
        thread1.start();
        thread2.start();
        try {
            //等待这两个线程结束!!
            thread1.join();
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Room 1 Vacancies:  %d\n", cinema.getVacanciesCinema1());
        System.out.printf("Room 2 Vacancies:  %d\n", cinema.getVacanciesCinerna2());
    }
}

//电影院类
class Cinema{
    private long vacanciesCinema1;
    private long vacanciesCinema2;
    private final Object controlCinema1,controlCinema2;
    public Cinema(){
        controlCinema1 = new Object();
        controlCinema2 = new Object();
        vacanciesCinema1 = 20;
        vacanciesCinema2 = 20;
    }
    public boolean sellTickets1(int number) {
        synchronized (controlCinema1) {
            if(number < vacanciesCinema1){
                vacanciesCinema1 -= number;
                return true;
            }else{
                return false;
            }
        }
    }
    public boolean sellTickets2(int number) {
        synchronized (controlCinema2) {
            if(number < vacanciesCinema2){
                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 getVacanciesCinerna2(){
        return vacanciesCinema2;
    }
}

//售票处1
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);
    }
}

//售票处2
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);
    }
}

用synchronized关键字保护代码块时,我们使用对象作为它的传入参数。JVM保证同一时间只有一个线程能够访问这个对象保护的代码保护块(注意:我们一直谈论的是对象,不是类)。

备注:这个例子使用了一个对象来控制对vacanciesCinema1属性的访问,所以同一时间只有一个线程能够修改这个属性; 使用了另一个对象来控制vacanciesCinema2属性的访问,所以同一时间只有一个线程能够修改这个属性。但是,这个例子允许同时运行两个线程:一个修改vacancesCinema1属性,另一个修改vacanciesCinema2属性。

时间: 2024-08-21 12:26:11

线程同步基础之使用非依赖属性实现同步的相关文章

WPF 让普通 CLR 属性支持 XAML 绑定(非依赖属性),这样 MarkupExtension 中定义的属性也能使用绑定了

原文:WPF 让普通 CLR 属性支持 XAML 绑定(非依赖属性),这样 MarkupExtension 中定义的属性也能使用绑定了 如果你写了一个 MarkupExtension 在 XAML 当中使用,你会发现你在 MarkupExtension 中定时的属性是无法使用 XAML 绑定的,因为 MarkupExtension 不是一个 DependencyObject. 本文将给出解决方案,让你能够在任意的类型中写出支持 XAML 绑定的属性:而不一定要依赖对象(DependencyObj

第二章线程同步基础

Java 7 并发编程实战手册目录 代码下载(https://github.com/Wang-Jun-Chao/java-concurrency) 第二章线程同步基础 2.1简介 多个执行线程共享一个资源的情景,是最常见的并发编程情景之一.在并发应用中常常遇到这样的情景:多个线程读或者写相同的数据,或者访问相同的文件或数据库连接. 为了防止这些共享资源可能出现的错误或数据不一致,我们必须实现一些机制来防止这些错误的发生. 为了解决这些问题,引入了临界区(Critical Section)概念,临

WPF系列 —— 控件添加依赖属性

依赖属性的概念,用途 ,如何新建与使用.本文用做一个自定义TimePicker控件来演示WPF的依赖属性的简单应用. 先上TimePicker的一个效果图. 概念 和 用途:依赖属性是对传统.net 属性的一种封装,使一个传统.net属性支持 WPF 中的 数据绑定.动画.样式 等功能. 新建:任意代码代码文件中 ,输入 propdp 再双击tab键.生成如下的代码块. MyProperty: 依赖属性的名称: ownerclass: 当前依赖属性绑定的所有类; new PropertyMeta

依赖属性

依赖属性基础   依赖属性是具有借用其他对象的数据的能力,具有依赖属性的对象为依赖对象.WPF所有UI都是依赖对象. 只有依赖属性才能做为Bingding的源或目标. DependencyObject具有GetValue()和SetValue()两个方法. 自定义一个依赖对象 public class Student3: DependencyObject//必须继承DependencyObject才能成为一个依赖对象 { // 定义依赖属性标准格式 public static readonly 

同步异步阻塞和非阻塞

同步异步阻塞和非阻塞 一.状态介绍 [ 在了解其他概念之前,我们首先要了解进程的几个状态.在程序运行的过程中,由于被操作系统的调度算法控制,程序会进入几个状态:就绪,运行和阻塞. 就绪(Ready)状态:当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态. 执行/运行(Running)状态当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态. 阻塞(Blocked)状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机

C# 多线程(二) 线程同步基础

本系列的第一篇简单介绍了线程的概念以及对线程的一些简单的操作,从这一篇开始讲解线程同步,线程同步是多线程技术的难点.线程同步基础由以下几个部分内容组成 1.同步要领(Synchronization Essentials) 2.锁(Locking) 3.线程安全(Thread Safety) 4.事件等待句柄(Signaling with Event Wait Handles) 5.同步上下文(Synchronization Contexts) 同步要领(Synchronization Essen

C# 多线程(二) 线程同步基础(上)

本系列的第一篇简单介绍了线程的概念以及对线程的一些简单的操作,从这一篇开始讲解线程同步,线程同步是多线程技术的难点.线程同步基础由以下几个部分内容组成 1.同步要领(Synchronization Essentials) 2.锁(Locking) 3.线程安全(Thread Safety) 4.事件等待句柄(Signaling with Event Wait Handles) 5.同步上下文(Synchronization Contexts) 同步要领(Synchronization Essen

C#中的线程(二) 线程同步基础

1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程完成                       锁系统 构成 目的 跨进程? 速度 lock 确保只有一个线程访问某个资源或某段代码. 否 快 Mutex 确保只有一个线程访问某个资源或某段代码.可被用于防止一个程序的多个实例同时运行. 是 中等 Semaphore 确保不超过指定数目的线程访问某

(二)线程同步基础

1.使用 synchronized实现同步方法 如果一个对象已经用synchronized声明,那么只允许一个执行线程访问它,如果其他线程试图访问这个对象的其他方法,它将被挂起,直到第一个线程执行完正在运行的方法.被synchronized声明的方法就是临界区. 对于非静态的方法被synchronized修饰后,同一时间内只能有一个线程访问这个对象的synchronized方法.即,每一个synchronized方法都控制着类成员变量的访问,要想访问被synchronized声明的方法,必须先获