线程安全概念:当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。

分析:当多个线程访问myThread的run方法时,以排队的方式进行处理(这里排对是按照CPU分配的先后顺序而定的),一个线程想要执行synchronized修饰的方法里的代码:1 尝试获得锁  2 如果拿到锁,执行synchronized代码体内容;拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,而且是多个线程同时去竞争这把锁。(也就是会有锁竞争的问题)

synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为"互斥区"或"临界区"。取得的锁都是对象锁,而不是把一段代码(方法)当做锁,所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。

锁对象的改变问题:例如下面代码中,当lock发生变化后,t1开始后,t2直接开始。如果去掉将lock改变的代码,则是t1结束后t2才会开始。但是同一对象属性的修改不会影响锁的情况,比如下面代码的lock现在是一个带属性的对象,如果改变该对象的属性,结果还是t1结束后t2才会开始。

package com.bjsxt.base.sync006;
/**
* 锁对象的改变问题
* @author alienware
*
*/
public class ChangeLock { private String lock = "lock"; private void method(){
synchronized (lock) {
try {
System.out.println("当前线程 : " + Thread.currentThread().getName() + "开始");
lock = "change lock";
Thread.sleep(2000);
System.out.println("当前线程 : " + Thread.currentThread().getName() + "结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) { final ChangeLock changeLock = new ChangeLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
changeLock.method();
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
changeLock.method();
}
},"t2");
t1.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
} }

 死锁问题:在设计程序时就应该避免双方相互持有对方的锁的情况,如下代码,会发生死锁问题,t1 进入lock1执行, t2 进入lock2执行。之后,t1去等待lock2对象解锁,t2去等待lock1对象解锁,这时谁也不能解锁,程序就会停在这里一直等待,这就是死锁问题。

package com.bjsxt.base.sync006;

/**
* 死锁问题,在设计程序时就应该避免双方相互持有对方的锁的情况
* @author alienware
*
*/
public class DeadLock implements Runnable{ private String tag;
private static Object lock1 = new Object();
private static Object lock2 = new Object(); public void setTag(String tag){
this.tag = tag;
} @Override
public void run() {
if(tag.equals("a")){
synchronized (lock1) {
try {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行");
}
}
}
if(tag.equals("b")){
synchronized (lock2) {
try {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock2执行");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock1) {
System.out.println("当前线程 : " + Thread.currentThread().getName() + " 进入lock1执行");
}
}
}
} public static void main(String[] args) { DeadLock d1 = new DeadLock();
d1.setTag("a");
DeadLock d2 = new DeadLock();
d2.setTag("b"); Thread t1 = new Thread(d1, "t1");
Thread t2 = new Thread(d2, "t2"); t1.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
} }

volatile:用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的值。volatile很容易被误用,用来进行原子性操作。volatile关键字不具备synchronized关键字的原子性(同步)

AtomicInteger:一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。注意:atomic类只保证本身方法的原子性,并不保证多次操作的原子性。比如说,我们使用AtomicInteger进行一次加十操作是具有原子性的,而同样是加十的操作,分成先加1,再加2,再加3,再加4这样四次操作,就不能保证原子性了。

脏读 :脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

在线程里调用变量变量必须用final修饰

wait释放锁,notify不释放锁。配合synchronized会有不实时的问题,这时有了下面的类。

CountDownLatch:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。

主要方法

public CountDownLatch(int count); 初始化计时器数量

public void countDown();

public void await() throws InterruptedException

构造方法参数指定了计数的次数

countDown方法,当前线程调用此方法,则计数减一

await方法,调用此方法会一直阻塞当前线程,直到计时器的值为0

ThreadLocal:ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。

多线程中的单例模式:

1.静态内部类--static inner class(饥汉模式)

package com.bjsxt.base.conn011;

public class Singletion {

    private static class InnerSingletion {
private static Singletion single = new Singletion();
} public static Singletion getInstance(){
return InnerSingletion.single;
} }

2.双重确认--dubble check instance(懒汉模式)

package com.bjsxt.base.conn011;

public class DubbleSingleton {

    private static DubbleSingleton ds;

    public  static DubbleSingleton getDs(){
if(ds == null){
try {
//模拟初始化对象的准备时间...
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (DubbleSingleton.class) {
if(ds == null){
ds = new DubbleSingleton();
}
}
}
return ds;
} public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t3"); t1.start();
t2.start();
t3.start();
} }

同步类容器(不建议使用)

并发类容器

并发Queue:

Futuer模式

Master-Worker模式

最新文章

  1. EMC起步:华为交换机拆解
  2. HDU 5769 后缀数组
  3. RAC 数据库的启动与关闭
  4. 转:linux下面/usr/local和opt目录有何区别
  5. A*算法完全理解
  6. RabbitMQ消息队列安装和配置以及推送消息
  7. .net 中文显示乱码问题(Chinese display with messy code)
  8. windows/Linux下安装maven
  9. Java的常用包
  10. 10676 涂鸦跳跃(sort)
  11. 软工+C(2017第1期) 题目设计、点评和评分
  12. centos6.5中rpm包安装mysql5.7(初始化出错如何解决)
  13. JSON WEB Token(JWT)
  14. Linux内核入门到放弃-内存管理-《深入Linux内核架构》笔记
  15. python基础一 ------如何根据字典值对字典进行"排序"
  16. Docker镜像常用命令
  17. 002-读书笔记-企业IT架构转型之道-阿里巴巴中台战略思想与架构实战-第二章 构建业务中台的基础-共享服务体系简介
  18. awk详解2
  19. Android开发Tips(5)
  20. (转)使用异步Python 3.6和Redis编写快速应用程序

热门文章

  1. Windows获取物理内存的2种方式 - 随笔记录
  2. Struts2进阶学习3
  3. 【原创】如何治疗使用python中re模块group、groups与findall分组匹配后产生的“眩晕反应”
  4. iOS 开发中保留小数问题
  5. .Net Core On Liunx 环境搭建之安装Mysql8
  6. 中恳中笨 搭建flask封装环境
  7. kuangbin 最小生成树
  8. HDU暑假多校第三场H.Monster Hunter
  9. c++实验3类和对象
  10. mono webreques https exception