Java同步学习(持续更新)
在需要考虑线程安全性的场合,可以考虑以下五种方式来实现线程的安全性:
1.同步方法
即有synchronized关键字修饰的方法。
由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,
1,该类的对象可以被多个线程安全的访问。
2,每个线程调用该对象的任意方法之后,都将得到正确的结果。
3,每个线程调用该对象的任意方法之后,该对象状态依然保持合理状态。
注:synchronized关键字可以修饰方法,也可以修饰代码块,但不能修饰构造器,属性等。
1。每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
2。将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行
的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。
package com.test;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDao {
private Connection conn;// ①一个非线程安全的变量
public void addTopic() throws SQLException {
Statement stat = conn.createStatement();// ②引用非线程安全变量
// …
}
}
conn是成员变量,因为addTopic()方法是非线程安全的,必须在使用时创建一个新TopicDao实例(非singleton)。下面使用ThreadLocal对conn这个非线程安全的“状态”进行改造:
TestDao:线程安全
package com.test;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
public class TestDaoNew {
// ①使用ThreadLocal保存Connection变量
private static ThreadLocal<Connection> connThreadLocal = new ThreadLocal<Connection>();
public static Connection getConnection() {
// ②如果connThreadLocal没有本线程对应的Connection创建一个新的Connection,
// 并将其保存到线程本地变量中。
if (connThreadLocal.get() == null) {
Connection conn = getConnection();
connThreadLocal.set(conn);
return conn;
} else {
return connThreadLocal.get();// ③直接返回线程本地变量
}
}
public void addTopic() throws SQLException {
// ④从ThreadLocal中获取线程对应的Connection
Statement stat = getConnection().createStatement();
}
}
不 同的线程在使用TopicDao时,先判断connThreadLocal.get()是否是null,如果是null,则说明当前线程还没有对应的 Connection对象,这时创建一个Connection对象并添加到本地线程变量中;如果不为null,则说明当前的线程已经拥有了 Connection对象,直接使用就可以了。这样,就保证了不同的线程使用线程相关的Connection,而不会使用其它线程的 Connection。因此,这个TopicDao就可以做到singleton共享了。
当然,这个例子本身很粗糙,将Connection的ThreadLocal直接放在DAO只能做到本DAO的多个方法共享Connection时不 发生线程安全问题,但无法和其它DAO共用同一个Connection,要做到同一事务多DAO共享同一Connection,必须在一个共同的外部类使 用ThreadLocal保存Connection。
ConnectionManager.java
package com.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionManager {
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
@Override
protected Connection initialValue() {
Connection conn = null;
try {
conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/test", "username",
"password");
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
};
public static Connection getConnection() {
return connectionHolder.get();
}
public static void setConnection(Connection conn) {
connectionHolder.set(conn);
}
}
1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,
如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断
如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情
ReentrantLock获取锁定与三种方式:
a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁
b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
c)tryLock(long timeout,TimeUnit unit), 如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断
2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异
常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到
finally{}中
3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;
下面内容 是转载 http://zzhonghe.iteye.com/blog/826162
5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增加了ReentrantLock,以及各种Atomic类。了解其性能的优劣程度,有助与我们在特定的情形下做出正确的选择。
总体的结论先摆出来:
synchronized:
在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。
ReentrantLock:
ReentrantLock
提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞
争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而
ReentrantLock确还能维持常态。
Atomic:
和上面的类似,不激烈情况下,性能比synchronized略
逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一
段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。
所以,我们写同步的时候,优先考虑synchronized,如果有特殊需要,再进一步优化。ReentrantLock和Atomic如果用的不好,不仅不能提高性能,还可能带来灾难。
Java同步学习(持续更新)的更多相关文章
- MongoDB学习——持续更新
參考MongoDB权威指南,学习阶段.大家多多交流问题.持续更新本文 MongoDB的长处 MongoDB具有丰富的数据模型,是面向文档的数据库. easy扩展.能够在多台server之间切割数据. ...
- Java名词术语---持续更新
在看技术文档的过程中,经常会出现新的java缩写术语,很多时候都不知道它们是什么,在这里记下,持续更新. ——————————————————————————————————————————————— ...
- 2019春招面试高频题(Java版),持续更新(答案来自互联网)
第一模块--并发与多线程 Java多线程方法: 实现Runnable接口, 继承thread类, 使用线程池 操作系统层面的进程与线程(对JAVA多线程和高并发有了解吗?) 计算机资源=存储资源+计算 ...
- 常见算法合集[java源码+持续更新中...]
一.引子 本文搜集从各种资源上搜集高频面试算法,慢慢填充...每个算法都亲测可运行,原理有注释.Talk is cheap,show me the code! 走你~ 二.常见算法 2.1 判断单向链 ...
- Java基础——集合(持续更新中)
集合框架 Java.util.Collection Collection接口中的共性功能 1,添加 booblean add(Object obj); 往该集合中添加元素,一次添加一个 boolea ...
- 读书笔记|Windows 调试原理学习|持续更新
关于调试方面的学习笔记,主要来源于<软件调试>的读书笔记和梦织未来论坛的视频教程 1.调试器使用一个死循环监听调试信息. DebugActiveProcess(PID);while(TRU ...
- Java笔记(持续更新中)
Java语言的特点: 面向对象(封装,继承,多态) 平台无关性(JVM运行.class文件) 语言(泛型,Lambda) 类库(集合,并发,网络,IO/NIO) JRE(Java运行环境,JVM,类 ...
- java并发编程[持续更新]
目录 java并发编程 1.常用类介绍 Semaphore 2.名词解释 2.1 线程安全 2.2 可重入锁和不可重入锁 java并发编程 1.常用类介绍 Semaphore Semaphore 类是 ...
- Java基础——多线程(持续更新中)
如何建立一个执行路径呢? 通过查询API文档 java.lang.Thread类 该类的描述中有创建线程的两种方式 1.继承Thread类 (1).将类声明为 Thread 的子类 (2).该子类应重 ...
随机推荐
- 基于Python——实现远程下载sftp文件(只下载.zip文件)
[背景]远程下载发布包等文件时,总是要使用WinSCP等工具登陆拖动.今天就介绍一种使用python下载文件到本地的方法. [代码实现] import paramiko # paramiko模块,基于 ...
- 1.3 第一个Go程序
1.3.1 Hello Go // hello.go package main import ( "fmt" ) func main() { fmt.Println("H ...
- js利用sort()方法实现数组排序
1.number类型排序 let aa = [1,11,2,4,3] aa.sort() console.log(aa) //[1,11,2,3,4] aa.sort((a,b)=>a-b) c ...
- css样式 + 特殊符号
color控制字体颜色 十六进制值 #cc0066: font-size控制字体大小 单位 px / % / em / rem:像素 / 相对于父级元素 / 取决自己使用字体大小 / 取决于根元素ht ...
- Python使用MySQL数据库(新)(转)
http://www.cnblogs.com/fnng/p/3565912.html 一,安装mysql 如果是windows 用户,mysql 的安装非常简单,直接下载安装文件,双击安装文件一步一步 ...
- 2/19 学习笔记(for in 、 del语句)
for x in ...循环就是把每个元素代入变量x,然后执行缩进块的语句 del语句作用在变量上,而不是数据对象上 列表可以修改,而字符串和元组不能
- 不得不补:PHP的JSON, SQL
不管怎么说,还是得感谢慕课网,提供了很多免费的视频教学. 学习自: https://www.imooc.com/view/68 前端页面: <!DOCTYPE html> <html ...
- tcl脚本直接执行脚本中中文识别不了的处理
上一篇说tcl中文乱码是因为我写了个bat调用该脚本,但是脚本中的中文路径是乱码.今天刚好有时间进行解决下: 首先看看调用代码 "./bin/base-tcl8.6-thread-win32 ...
- Fiddler中session请求/响应类型与图标含义
近期在看fiddler抓包工具,发现前面都会有小图标显示,不同的图标代表了不同的含义,通过查询,整理如下: 请求发送到服务器 从服务器下载响应结果 请求在断点处被暂停 响应在断点处被暂停 请 ...
- 剑指Offer 37. 数字在排序数组中出现的次数 (数组)
题目描述 统计一个数字在排序数组中出现的次数. 题目地址 https://www.nowcoder.com/practice/70610bf967994b22bb1c26f9ae901fa2?tpId ...