---
title: 并发编程--线程基础
date: 2018-07-05 09:12:57
categories:
- 并发编程
---

<Excerpt in index | 首页摘要>
<!-- more -->
<The rest of contents | 余下全文>

并发编程--线程基础

1. 当多个线程访问某一个类(对象或方法)时:这个类始终都能表现正确的行为,那么这个类(对象或方法)就是线程安全的
2. 多个线程多个锁:每个线程都可以拿到自己指定的锁,分别获取锁之后,执行synchronized修饰的方法体内容;
3. 对象锁的同步和异步问题;
4. 脏读

一.线程安全

#### 1. 当多个线程访问某一个类(对象或方法)时:这个类始终都能表现正确的行为,那么这个类(对象或方法)就是线程安全的。
Synchronized :可以在任意对象以及方法上加锁,而加锁的这段代码成为“互斥区”/"临界区"。
实例 thread01:
分析:
当多个线程访问myThread的run方法时,以排队的方式进行处理(这里排对是按照 CPU分配的先后顺序而定的),一个线程想要执行synchronized修饰的方法里的代码:
* 1 尝试获得锁
* 2 如果拿到锁,执行synchronized代码体内容;拿不到锁,这个线程就会不断的尝试获得这把锁,直到拿到为止,而且是多个线程同时去竞争这把锁。(也就是会有锁竞争的问题)

```java
/*** 线程安全概念:当多个线程访问某一个类(对象或方法)时,这个对象始终都能表现出正确的行为,那么这个类(对象或方法)就是线程安全的。* synchronized:可以在任意对象及方法上加锁,而加锁的这段代码称为"互斥区"或"临界区"* @@author Maozw**/
public class MyThread extends Thread{private int count = 5 ;//synchronized加锁@Overridepublic synchronized void run(){count--;System.out.println(currentThread().getName() + " count = "+ count);}public static void main(String[] args) {MyThread myThread = new MyThread();Thread t1 = new Thread(myThread,"t1");Thread t2 = new Thread(myThread,"t2");Thread t3 = new Thread(myThread,"t3");Thread t4 = new Thread(myThread,"t4");Thread t5 = new Thread(myThread,"t5");t1.start();t2.start();t3.start();t4.start();t5.start();}
}

  

2. 多个线程多个锁:每个线程都可以拿到自己指定的锁,分别获取锁之后,执行synchronized修饰的方法体内容;

说明:

* 关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当做锁;
所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),两个对象,两个线程分别获得是两个不同的锁,互不影响;
* 有一种情况列外:即静态方法上加synchronized关键字:
在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。
实例:MultiThread.java

/*** 关键字synchronized取得的锁都是对象锁,而不是把一段代码(方法)当做锁,* 所以代码中哪个线程先执行synchronized关键字的方法,哪个线程就持有该方法所属对象的锁(Lock),* 在静态方法上加synchronized关键字,表示锁定.class类,类一级别的锁(独占.class类)。* @author Maozw**/
public class MultiThread {private int num = 0;/** static */public synchronized void printNum(String tag){try {if(tag.equals("a")){num = 100;System.out.println("tag a, set num over!");Thread.sleep(1000);} else {num = 200;System.out.println("tag b, set num over!");}System.out.println("tag " + tag + ", num = " + num);} catch (InterruptedException e) {e.printStackTrace();}}//注意观察run方法输出顺序public static void main(String[] args) {//俩个不同的对象final MultiThread m1 = new MultiThread();final MultiThread m2 = new MultiThread();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {m1.printNum("a");}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {m2.printNum("b");}});       t1.start();t2.start();}
}

3. 对象锁的同步和异步问题

* 同步:synchronized
同步的概念就是共享,其实需要记住线程要"共享"变量就可以,如果没有共享变量就无所谓同步;
* 异步:asynchronized
异步的概念就是独立:相互之间不受制约。
同步的目的就是为了线程安全:对于线程安全无非就是满足俩特性:
* 原子性
* 可见性

实例MyObject.java
说明:
* t1线程先持有object对象的Lock锁,t2线程可以以异步的方式调用对象中的非synchronized修饰的方法
* t1线程先持有object对象的Lock锁,t2线程如果在这个时候调用对象中的同步(synchronized)方法则需等待,也就是同步

/*** 对象锁的同步和异步问题* @@author Maozw**/
public class MyObject {public synchronized void method1(){try {System.out.println(Thread.currentThread().getName());Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}}/** synchronized */public void method2(){System.out.println(Thread.currentThread().getName());}public static void main(String[] args) {final MyObject mo = new MyObject();/*** 分析:* t1线程先持有object对象的Lock锁,t2线程可以以异步的方式调用对象中的非synchronized修饰的方法* t1线程先持有object对象的Lock锁,t2线程如果在这个时候调用对象中的同步(synchronized)方法则需等待,也就是同步*/Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {mo.method1();}},"t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {mo.method2();}},"t2");t1.start();t2.start();}
}

  

4. 脏读

对于对象的同步和异步方法,我们设计程序一定要考虑整体,不然会出现数据不一致的问题,经典Demo就是脏读
实例:DirtyRead.java
说明:
* 在对一个对象的方法进行加锁的时候,需要考虑业务的整体性,即为setValue/getValue方法同事加锁synchronized同步关键字,保证业务的原子性,不然会出现数据不一致的问题

/*** 业务整体需要使用完整的synchronized,保持业务的原子性。* @@author Maozw**/
public class DirtyRead {private String username = "bjsxt";private String password = "123";public synchronized void setValue(String username, String password){this.username = username;try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}this.password = password;System.out.println("setValue最终结果:username = " + username + " , password = " + password);}public void getValue(){System.out.println("getValue方法得到:username = " + this.username + " , password = " + this.password);}public static void main(String[] args) throws Exception{final DirtyRead dr = new DirtyRead();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {dr.setValue("z3", "456");      }});t1.start();Thread.sleep(1000);dr.getValue();}
}

 

转载于:https://www.cnblogs.com/Mao-admin/p/9988214.html

2.并发编程--线程基础相关推荐

  1. 判断线程是否执行完毕_Java并发编程 | 线程核心机制,基础概念扩展

    源码地址:GitHub || GitEE 一.线程基本机制 1.概念描述 并发编程的特点是:可以将程序划分为多个分离且独立运行的任务,通过线程来驱动这些独立的任务执行,从而提升整体的效率.下面提供一个 ...

  2. python 线程同步_Python并发编程-线程同步(线程安全)

    Python并发编程-线程同步(线程安全) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 线程同步,线程间协调,通过某种技术,让一个线程访问某些数据时,其它线程不能访问这些数据,直 ...

  3. 学习笔记:Java 并发编程①_基础知识入门

    若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 视频下载: ...

  4. Java 并发编程 -- 线程池源码实战

    一.概述 小编在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写的太简单,只写了一点皮毛,要么就是是晦涩难懂,看完之后几乎都 ...

  5. Java并发编程实战基础概要

    文章目录 Java并发编程实战基础概要 开篇 多线程问题有啥难点呢? 为啥要学习并发编程? 并发问题的根源是什么? CPU切换线程执导致的原子性问题是如何发生的? 缓存导致的可见性问题是如何发生的? ...

  6. 高并发编程-线程通信_使用wait和notify进行线程间的通信2_多生产者多消费者导致程序假死原因分析

    文章目录 概述 jstack或者可视化工具检测是否死锁(没有) 原因分析 概述 高并发编程-线程通信_使用wait和notify进行线程间的通信 - 遗留问题 我们看到了 应用卡住了 .... 怀疑是 ...

  7. 并发编程——线程协作

    并发编程--线程协作 ​ 前面学习了线程,那么并发编程中,如何协调多个线程来开发呢? Semaphore ​ 信号量跟前面将的同步互斥解决方案--信号量是一个东西,这是JDK的信号量实现. 源码分析 ...

  8. Java并发编程-线程安全基础

    线程安全基础 1.线程安全问题 2.账户取款案例 3.同步代码块synchronized synchronized的理解 java中有三大变量的线程安全问题 在实例方法上使用synchronized ...

  9. 【Java_多线程并发编程】基础篇—线程状态及实现多线程的两种方式

    1.Java多线程的概念 同一时间段内,位于同一处理器上多个已开启但未执行完毕的线程叫做多线程.他们通过轮寻获得CPU处理时间,从而在宏观上构成一种同时在执行的假象,实质上在任意时刻只有一个线程获得C ...

  10. 【从入门到放弃-Java】并发编程-线程安全

    概述 并发编程,即多条线程在同一时间段内"同时"运行. 在多处理器系统已经普及的今天,多线程能发挥出其优势,如:一个8核cpu的服务器,如果只使用单线程的话,将有7个处理器被闲置, ...

最新文章

  1. FCKeditor 2.6 安装配置使用指南(asp)
  2. Lucene Inverted index(倒排索引)原来快速入门
  3. unzipping/Users/xq/.gradle/wrapper /dists/gradle-3.3-all/55gk2rcmfc6p2dg9u9ohc3hw9/gradle-3.3-all.zi
  4. 部署kafka kafka的service容器和zookeeper kafka客户端 Elasticsearch的客户端
  5. Github常用搜索指令(毕设资料搜索必备)
  6. BNU OJ 第26303 题 Touchscreen Keyboard
  7. 洛谷P5703、P5704、P5705、P5706题题解(Java语言描述)
  8. 修改map.html,HTML map 标签 | 菜鸟教程
  9. 使用history.back()出现警告: 网页已过期的解决办法
  10. WebSocket使用教程 - 带完整实例--网址:https://my.oschina.net/u/1266171/blog/357488
  11. clockworkmod CWM简单介绍
  12. sniffer与网络执法官,p2p终结者的简单对比
  13. 网页制作中PS图像处理的应用
  14. Mezzanine汉化
  15. matlab自学入门
  16. evict和clear
  17. 计算机用户被停用,Win10电脑中Administrator账户被停用如何解决
  18. 织梦图集php,织梦怎么为新图集页面增加图片下载功能
  19. com.netflix.hystrix.exception.HystrixRuntimeException short-circuited and no fallback available
  20. 碎碎念No.01 你是个自信的人嘛

热门文章

  1. vsftp的简单搭建
  2. label自动换行代码和DataGrid中删除最后一页的记录时出错的解决办法以及HTML小TIPS:强制HTML表格断行...
  3. 操作手机_适合单手操作的手机,它们是王者
  4. el-tree多选获取选中的节点ID
  5. 关于SDWebImage
  6. 解决.net core 读取json文件中文乱码的问题
  7. JProfiler11安装,选择IDE
  8. Perhaps you should add the directory containing libpcre.pc to the PKG_CONFIG_PATH
  9. Linux打印cups API及代码范例链接
  10. LINUX SHELL多条件(与、或)if判断怎么写?