Java中的线程同步
Java 中的线程同步问题:
1. 线程同步:
对于访问同一份资源的多个线程之间, 来进行协调的这个东西.
2. 同步方法:
当某个对象调用了同步方法时, 该对象上的其它同步方法必须等待该同步方法执行完毕后, 才能被执行.
3. 同步块:
通常将共享资源的操作放置在 synchronized 定义的区域内, 这样当其它线程也获取到这个锁时, 必须等待锁被释放, 才能进入该区域.
Demo_1:
class Timer {
private static int num = 0;
public void add(String name) {
num++;
try {
Thread.sleep(100); // 即使不写 Thread.sleep(100), 这个结果可能是对的,也有可能是错的, 不确定. 中间还是有可能被打断.
} catch (InterruptedException e) {
}
System.out.println(name+", 你是第 "+num+"个使用timer的线程");
}
}
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();
}
@Override
public void run() {
timer.add(Thread.currentThread().getName());
}
}
会出现的运行结果:
t1, 你是第 2个使用timer的线程
t2, 你是第 2个使用timer的线程
原因:这个线程在执行 add()方法的时候, 被另外一个线程给打断了.
解决办法:
num++;
try {Thread.sleep(100);
} catch (InterruptedException e) {}
上面这几句话, 应该作为一个原子性的输出, 你不应该在中途打断.
第一种解决办法:采用同步块, 如 Demo_2
Demo_2:
class Timer {
private static int num = 0;
public void add(String name) {
synchronized(this){ // 同步块
num++;
try {Thread.sleep(100);
} catch (InterruptedException e) {}
System.out.println(name+", 你是第 "+num+"个使用timer的线程");
}
}
}
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();
}
@Override
public void run() {
timer.add(Thread.currentThread().getName());
}
}
// 运行结果如下:
// t1, 你是第 1个使用timer的线程
// t2, 你是第 2个使用timer的线程
【注】:既然锁定了当前对象了, 那么这个 num 也就锁定了, 它里面的成员变量当然也锁定(互斥锁).
【注】:锁定当前对象:这执行后面的大括号里面的语句的过程中, 一个线程的执行过程中, 不会被另外一个线程锁打断.
一旦某个线程已经进入到锁定的区域当中, 那么你放心, 不可能有另外一个线程也在里面(锁的机制).
第二种解决办法:采用同步块, 如 Demo_3
Demo_3:
class Timer {
private static int num = 0;
public synchronized void add(String name) { //同步方法
num++;
try {Thread.sleep(100);
} catch (InterruptedException e) {}
System.out.println(name+", 你是第 "+num+"个使用timer的线程");
}
}
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();
}
@Override
public void run() {
timer.add(Thread.currentThread().getName());
}
}
// 运行结果如下:
// t1, 你是第 1个使用timer的线程
// t2, 你是第 2个使用timer的线程
分析 Demo_3 的执行过程:
t1 开始执行, 调用 add() 方法, num++, 然后 t1 睡着了, 睡着了也没关系, t1 睡着也抱着那把锁.
别人(t2)也进不来, 你必须等它执行完了, 你才可以继续执行.
睡着了, 也不放开那把锁, 你也没办法.
4. 线程同步总结:
4.1. 在 Java 语言中, 引入了对象互斥锁的概念, 保证共享数据操作的完整性. 每个对象都对应于一个可称为"互斥锁"的标记,
这个标记保证在任一时刻, 只有一个线程访问该对象.
4.2. 关键字 synchronized 与对象的互斥锁联系. 当某个对象用 synchronized 来修饰时, 表明该对象在任一时刻只能由一个线程访问.
Java中的线程同步的更多相关文章
- java中实现线程同步
为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他 ...
- Java中处理线程同步
引自:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8295527和http://m.blog.csdn.net/blog/undoner/1 ...
- Java中实现线程同步的三种方法
实现同步的三种方法 多线程共享数据时,会发生线程不安全的情况,多线程共享数据必须同步. 实现同步的三种方法: 使用同步代码块 使用同步方法 使用互斥锁ReetrantLock(更灵活的代码控制) 代码 ...
- Java中的线程同步机制
一.首先为什么线程需要同步? 1.多线程安全问题的原因 A:有多线程环境 B:有共享数据 C:有多条语句操作共享数据 2. //未完待续后面会继续更新
- 浅谈利用同步机制解决Java中的线程安全问题
我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...
- 关于Java中的线程安全(线程同步)
java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么叫 ...
- Java中的线程Thread总结
首先来看一张图,下面这张图很清晰的说明了线程的状态与Thread中的各个方法之间的关系,很经典的! 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口. 要注意的是Threa ...
- 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)
Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...
- Java多线程与线程同步
六.多线程,线程,同步 ①概念: 并行:指两个或多个在时间同一时刻发生(同时发生) 并发:指两个或多个事件在同一时间段内发生 具体概念: 在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多 ...
随机推荐
- PHP封装CURL
CURL是一个非常强大的开源库,支持很多协议,包括HTTP.FTP.TELNET等,我们使用它来发送HTTP请求.它给我 们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且支持HTTPS ...
- ThinkPHP5.1完全开发手册.CHM离线版下载
ThinkPHP5.1完全开发手册.CHM离线版下载 ThinkPHP5.1完全开发手册离线版.CHM下载地址 百度云:链接: https://pan.baidu.com/s/1b4jKJN-8UyI ...
- OpenWrt超时检测
参考http://www.right.com.cn/forum/thread-261702-1-1.html vim /home/ihid/chaos_calmer/feeds/luci/module ...
- 001-快速排序(C++实现)
快速排序的基本实现 快速排序算法是一种基于交换的高效的排序算法,它采用了分治法的思想: 1.从数列中取出一个数作为基准数(枢轴,pivot). 2.将数组进行划分(partition),将比基准数大的 ...
- day 3 创建窗口,移动-函数版
1.创建窗口 #-*- coding:utf-8 -*- import pygame import time def main(): #1.创建窗口 screen = pygame.display.s ...
- LeetCode:49. Group Anagrams(Medium)
1. 原题链接 https://leetcode.com/problems/group-anagrams/description/ 2. 题目要求 给定一个字符串数组,将数组中包含相同字母的元素放在同 ...
- 最新flowable研究学习及其汉化flowable6.3中文
flowable 是activiti的分支,现在感觉比activiti要强大一些,官网是 https://flowable.org/ 下载最新的6.31版本. 放到tomcat下面,汉化需要对flow ...
- APP上下左右滑动屏幕的处理
#获得机器屏幕大小x,y driver = self.driver def getSize(): x = driver.get_window_size()['width'] y = driver.ge ...
- 即刻开始使用Kotlin开发Android的12个原因(KAD 30)
作者:Antonio Leiva 时间:Jul, 11, 2017 原文链接:https://antonioleiva.com/reasons-kotlin-android/ 这组文章已到最后了,它们 ...
- Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis
第5章--MyBatis MyBatis入门 Abstract: 数据库框架的工作原理和使用方法(以MyBatis为例) 面向对象的世界与关系型数据库的鸿沟: 面向对象世界中的数据是对象: 关系型数据 ...