java同步和互斥【用具体程序说明】
java同步和互斥【用具体程序说明】
通俗点说就是,当调用A的含有synchronized的方法是,A会被枷锁,此时A中其他含有synchronized方法只有等到前一个方法调用完毕释放了锁才能被调用
具体说明见另一篇博客<<java同步和互斥【相关原理】》
下面看看具体的程序,其中,Timer中的字段num是共享资源
- package com.bankht.synchronize;
- public class TestSync implements Runnable {
- Timer timer = new Timer();
- public static void main(String[] args) {
- TestSync test = new TestSync();
- Thread t1 = new Thread(test);
- Thread t2 = new Thread(test);
- t1.setName("t1");
- t2.setName("t2");
- t1.start();
- t2.start();
- }
- public void run() {
- timer.add(Thread.currentThread().getName());
- }
- }
- class Timer {
- private static int num = 0;
- public void add(String name) {
- num++;
- try {
- Thread.sleep(1);
- } catch (InterruptedException e) {
- }
- System.out.println(name + ", 你是第" + num + "个使用timer的线程");
- }
- }
- 由于没有同步,所以运行结果如下所示
t1, 你是第2个使用timer的线程
t2, 你是第2个使用timer的线程
也就是说当线程一运行到num++的时候被打线程2打断了,由于java中递增和递减操作均不是原子操作,所以本程序中即使没有调用sleep,也会出现这种被打断的情况
下面看看同步的效果
- public void add(String name) {
- synchronized (this) {//同步
- num++;
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
- System.out.println(name + ", 你是第" + num + "个使用timer的线程");
- }
- }
这样运行结果就会出是正确的
t1, 你是第1个使用timer的线程
t2, 你是第2个使用timer的线程
但是,下面为了说明问题把TestSync里面的run方法改成如下所示
- public void run() {
- /
- time.add(Thread.currentThread().getName());
- try {
- Thread.sleep(1000);//为了显示结果,让其睡眠一秒
- } catch (InterruptedException ex) {
- Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);
- }
- System.out.println(Thread.currentThread().getName() + "----");
- }
那么在此运行就是
t1, 你是第1个使用timer的线程
t2, 你是第2个使用timer的线程
t1--------
t2--------
而不是你所想象的
t1, 你是第1个使用timer的线程
t1----
t2, 你是第2个使用timer的线程
t2----
原因就是在线程t1在睡眠的时候,线程t2切换进来,执行了一次,怎样得到正确的结果呢,下面把TestSync里面的run方法做如下改进就可以得到上面预期的结果
- public void run() {
- synchronized(time){
- time.add(Thread.currentThread().getName());
- try {
- Thread.sleep(3000);
- } catch (InterruptedException ex) {
- Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);
- }
- System.out.println(Thread.currentThread().getName() + "----");
- }
- }
因为t1先获得time的锁,所以在执行完run里面的同步块之前,即使sleep(),t2也不会执行,因为t2没有获得time的锁,且sleep()操作也不释放锁(这也是和wait的巨大区别)
附录:TestSync.java全部代码
- package com.bankht.synchronize;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- public class TestSync implements Runnable {
- Timer timer = new Timer();
- public static void main(String[] args) {
- TestSync test = new TestSync();
- Thread t1 = new Thread(test);
- Thread t2 = new Thread(test);
- t1.setName("t1");
- t2.setName("t2");
- t1.start();
- t2.start();
- }
- // public void run() {
- // timer.add(Thread.currentThread().getName());
- // }
- // public void run() {
- // timer.add(Thread.currentThread().getName());
- // try {
- // Thread.sleep(1000);//为了显示结果,让其睡眠一秒
- // } catch (InterruptedException ex) {
- // Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);
- // }
- // System.out.println(Thread.currentThread().getName() + "----");
- // }
- public void run() {
- synchronized(timer){
- timer.add(Thread.currentThread().getName());
- try {
- Thread.sleep(3000);
- } catch (InterruptedException ex) {
- Logger.getLogger(TestSync.class.getName()).log(Level.SEVERE, null, ex);
- }
- System.out.println(Thread.currentThread().getName() + "----");
- }
- }
- }
- class Timer {
- private static int num = 0;
- // public void add(String name) {
- //
- // num++;
- // try {
- // Thread.sleep(1000);
- // } catch (InterruptedException e) {
- // }
- // System.out.println(name + ", 你是第" + num + "个使用timer的线程");
- //
- // }
- public void add(String name) {
- synchronized (this) {// 同步
- num++;
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
- System.out.println(name + ", 你是第" + num + "个使用timer的线程");
- }
- }
- }
java同步和互斥【用具体程序说明】的更多相关文章
- 【Java并发基础】并发编程领域的三个问题:分工、同步和互斥
前言 可以将Java并发编程抽象为三个核心问题:分工.同步和互斥. 这三个问题的产生源自对性能的需求.最初时,为提高计算机的效率,当IO在等待时不让CPU空闲,于是就出现了分时操作系统也就出现了并发. ...
- 监视锁——Java同步的基本思想
翻译人员: 铁锚翻译时间: 2013年11月13日原文链接: Monitors – The Basic Idea of Java synchronization如果你上过操作系统课程,你就知道监视锁( ...
- 死磕 java同步系列之zookeeper分布式锁
问题 (1)zookeeper如何实现分布式锁? (2)zookeeper分布式锁有哪些优点? (3)zookeeper分布式锁有哪些缺点? 简介 zooKeeper是一个分布式的,开放源码的分布式应 ...
- 死磕 java同步系列之ReentrantReadWriteLock源码解析
问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...
- Java同步与异步
一.关键字: thread(线程).thread-safe(线程安全).intercurrent(并发的) synchronized(同步的).asynchronized(异步的). volatile ...
- 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...
- exec函数族,守护进程,线程同步和互斥
2015.3.2 进程和程序有三点不同:1,存在位置不同,程序:硬盘,磁盘.进程:内存2. 程序是静态的,进程是动态的 执行./a.out -->bash->bash程序调用fork()- ...
- Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间, ...
- Windows下C++多线程同步与互斥简单运用
1. 互斥量,Mutex #include <Windows.h> #include <iostream> using namespace std; DWORD WINAPI ...
随机推荐
- 微信小程序onlaunch异步,首页onLoad先执行?
按照原理是小程序初始化时会先触发APP里的onLaunch事件,之后再执行页面Page里的onLoad事件.但实际请求时在onLaunch事件中请求获取数据,等待返回值的时候Page里的onLoad事 ...
- Android 开发第一项目——计算器的开发记录
2017.4.1 今天布局界面基本完成,现在写了一点事件绑定.计划是多用动态绑定,随时用随时改.关于布局方面,昨天弄到很晚,原因是Layout使用错误,用的自带的,没仔细看,预览的时候没有问题但是真机 ...
- iOS 初探代码混淆(OC)
iOS 初探代码混淆(OC) 前言 自己做iOS开发也有几年的时间了,平时做完项目基本就直接打包上传到Appstore上,然后做上架操作了.但是最近,客户方面提出了代码安全的要求.说是要做代码混淆,这 ...
- Linux文件系统目录
Linux操作系统目录呈树形结构,文件系统只有一个根目录,其余文件都是从根目录下延伸出来的 上图是一个Linux文件系统目录的展现,现在我们来看一下文件系统目录下相关目录及其功能 根目录( / ) L ...
- 学习创建spring boot
一.什么是spring boot? Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开 ...
- 微信小程序实战练习(仿五洲到家微信版)
github地址(欢迎star):https://github.com/xiaobinwu/dj 版本:0.15.152900(暂未升级原因:升级后需要图片无法本地引用,必须使用image或是远程路径 ...
- css3 翻牌动画
最近做了一个特效,css是从网上找的,地址是这个: CSS3 animate flip下的纸牌翻转效果实例页面 把其中核心的css代码扒出来如下: /* The properties in this ...
- 软件测试第一次试验JUnit
一.Junit, hamcrest以及eclemma的安装 对于Junit和hamcrest的安装,我并没有从下载Junit和hamcrest相关的jar包然后通过build path导入到项目中,而 ...
- python修炼第四天
今天换了师傅.江湖人称景女神^o^. 女师傅讲的比较细,原理的比较多.初学者来说有些难.但是基本功是必须要打牢的.努力! 迭代器 迭代器,迭代的工具1 什么是迭代,指的是一个重复的过程,每一次重复称为 ...
- Python标准库--time模块的详解
time模块 - - -时间获取和转换 在我们学习time模块之前需要对以下的概念进行了解: 时间戳:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08 ...