Java马士兵高并发编程视频学习笔记(一)
1.同一个资源,同步和非同步的方法可以同时调用
package com.dingyu;
public class Y {
public synchronized void m1() {
System.out.println(Thread.currentThread().getName() + " m1 begin---------");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " m1 end---------");
}
public void m2() {
System.out.println(Thread.currentThread().getName() + " m2 begin---------");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " m2 end---------");
}
public static void main(String[] args) {
Y t = new Y();
// new Thread(()->t.m1(),"t1").start();
// new Thread(()->t.m2(),"t2").start();
new Thread(new Runnable() {
@Override
public void run() {
t.m1();
}
},"t1").start();;
new Thread(new Runnable() {
@Override
public void run() {
t.m2();
}
},"t2").start();;
}
}

可以看到t1先执行,如果不能同时调用那么t2是不能执行的,必须等t1结束,释放锁后才能调用,但这里t2确先执行了,所以是可以同时调用的。
2.对业务写代码进行加锁,对读代码不进行加锁,会产生脏读
package com.dingyu;
public class U {
private String name;
private double banlance;
public synchronized void set(String name, double balance) {
this.name = name;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.banlance = balance;
}
public double getBalance() {
return banlance;
}
public static void main(String[] args) {
U u = new U();
new Thread(() -> u.set("zhangsan", 500)).start();
System.out.println(u.getBalance());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(u.getBalance());
}
}

3.同线程内一个同步方法可以去调用另一个同步方法(重入锁 还有一种重入锁就是子类调用父类的同步方法)
package com.dingyu;
public class I {
public synchronized void m1() {
System.out.println("m1 start");
m2();
System.out.println("m1 end");
}
private synchronized void m2() {
System.out.println("m2 start");
System.out.println("m2 end");
}
public static void main(String[] args) {
I i = new I();
new Thread(() -> i.m1()).start();
}
}

4.模拟一个简单的死锁
package com.dingyu;
public class DeadLock {
private Object o1 = new Object();
private Object o2 = new Object();
public void m1() {
synchronized (o1) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (o2) {
System.out.println("如果出现这句话表示没有死锁");
}
}
}
public void m2() {
synchronized(o2) {
synchronized (o1) {
System.out.println("如果出现这句话表示没有死锁");
}
}
}
public static void main(String[] args) {
DeadLock deadLock=new DeadLock();
new Thread(()->deadLock.m1()).start();
new Thread(()->deadLock.m2()).start();
}
}
5.如果执行同步方法中出现异常,那么就会自动释放锁,如果不想释放锁,加上try catch
package com.dingyu;
public class ReleaseLock {
private int count = 0;
private int i = 0;
public synchronized void m1() {
while (true) {
System.out.println(Thread.currentThread().getName() + " " + count++);
if (count % 10 == 0)
i = 1 / 0;
}
}
public static void main(String[] args) {
ReleaseLock releaseLock = new ReleaseLock();
new Thread(() -> releaseLock.m1(), "t1").start();
new Thread(() -> releaseLock.m1(), "t2").start();
}
}

6.volatile关键字(无锁同步)
volatile关键字 每个线程都有自己的一小块内存,执行的时候会把变量copy过来,修改了后在写回对象,
执行m1方法的线程把 running读到内存里,与此同时主线程也把running读到内存,并进行修改,写回对象为false
但是执行m1的线程里的内存一直都是true啊(因为太忙了没空去刷新)所以会形成死循环,
volatile就是当running改了之后 *立马去通知其他线程,你们记得去主存刷新一下,一刷新,running为false,退出while循环。
package com.dingyu;
/**
* volatile关键字 每个线程都有自己的一小块内存,执行的时候会把变量copy过来,修改了后在写回对象,
* 执行m1方法的线程把 running读到内存里,与此同时主线程也把running读到内存,并进行修改,写回对象为false
* 但是执行m1的线程里的内存一直都是true啊(因为太忙了没空去刷新)所以会形成死循环,volatile就是当running改了之后
* 立马去通知其他线程,你们记得去主存刷新一下,一刷新,running为false,退出while循环。
* @author dingyu
*
*/
public class VolatileDemo {
private volatile boolean running = true; public void m1() {
System.out.println("m1 start");
while (running) { }
System.out.println("m1 end");
} public static void main(String[] args) {
VolatileDemo volatileDemo = new VolatileDemo();
new Thread(() -> volatileDemo.m1()).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
volatileDemo.running = false; }
}
7.voliatile 不能保证原子性 不能替换synchronized
package com.dingyu; /**
* voliatile 不能保证原子性 不能替换synchronized
*
* @author dingyu
*
*/
public class VolatileDemo02 {
public volatile int count = 0; public void m1() {
for (int i = 0; i <= 10000; i++)
count++;
} public static void main(String[] args) {
VolatileDemo02 volatileDemo02 = new VolatileDemo02();
for (int i = 0; i < 3; i++) {
new Thread(() -> volatileDemo02.m1()).start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(volatileDemo02.count);
}
}

8.多个原子类的方法之间不具备原子性
package com.dingyu; import java.util.concurrent.atomic.AtomicInteger; /**
* 原子类 具有原子性,但两个原子类的方法之间不具备原子性
*
* @author dingyu
*
*/
public class AtomicDemo {
private AtomicInteger count = new AtomicInteger(); public void m1() {
for (int i = 0; i < 100; i++) {
count.incrementAndGet();
//两个原子类的方法之间不具备原子性
count.incrementAndGet(); }
}
}
9.原子类的不具备可见性
package com.dingyu;
import java.util.concurrent.atomic.AtomicBoolean;
public class AtomicDemo02 {
public AtomicBoolean running = new AtomicBoolean(true);
public void m1() {
while (running.get()) {
}
}
public static void main(String[] args) {
AtomicDemo02 demo02 = new AtomicDemo02();
new Thread(()->demo02.m1()).start();
demo02.running.set(false);
}
}
10.锁是锁在堆内存的那个对象上,而不是引用
package com.dingyu; /**
* 锁是锁在堆内存的那个对象上,而不是引用
*
* @author dingyu
*
*/
public class ChangeReference {
public Object o = new Object(); public void m1() {
//锁o
synchronized (o) {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
} public static void main(String[] args) {
ChangeReference changeReference = new ChangeReference();
new Thread(() -> changeReference.m1(), "t1").start();//启动一个线程 叫t1
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
changeReference.o = new Object();//引用变了
new Thread(() -> changeReference.m1(),"t2").start();//启动线程 t2
}
}

11.不要锁字符串常量
package com.dingyu;
/**
* 不要锁字符串常量
* @author dingyu
*
*/
public class SynchronizedString {
private String s1 = "hello";
private String s2 = "hello"; public void m1() {
synchronized (s1) {
while(true) {}
}
} public void m2() {
synchronized (s2) {
System.out.println("m2 start");
}
} public static void main(String[] args) {
SynchronizedString synchronizedString = new SynchronizedString();
new Thread(()->synchronizedString.m1()).start();
new Thread(()->synchronizedString.m2()).start();
}
}
12.wait 让线程暂停,释放锁, notify 唤醒线程,不释放锁
package com.dingyu2; /**
* wait 让线程暂停,释放锁, notify 唤醒线程,不释放锁
*
* @author dingyu
*
*/
public class WaitAndNotyifyDemo {
private volatile int count = 0;
private Object lock = new Object(); public void m1() {
synchronized (lock) {
System.out.println("m1 start");
for (int i = 0; i < 10; i++) {
count++;
System.out.println(count);
if (count == 5) {
lock.notify();
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} }
} public void m2() {
synchronized (lock) {
System.out.println("m2 start");
if (count != 5) {
try {
System.out.println("m2 在等着 但把锁释放了");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("m2 end");
lock.notify();
}
} public static void main(String[] args) {
WaitAndNotyifyDemo waitAndNotyifyDemo = new WaitAndNotyifyDemo();
new Thread(() -> waitAndNotyifyDemo.m2()).start();
new Thread(() -> waitAndNotyifyDemo.m1()).start();
}
}
Java马士兵高并发编程视频学习笔记(一)的更多相关文章
- Java马士兵高并发编程视频学习笔记(二)
1.ReentrantLock的简单使用 Reentrant n.再进入 ReentrantLock 一个可重入互斥Lock具有与使用synchronized方法和语句访问的隐式监视锁相同的基本行为和 ...
- 《Java虚拟机并发编程》学习笔记
对<Java虚拟机并发编程>这本书真的是相见恨晚.以前对并发编程只是懂个皮毛,这本书让我对并发编程有了一个全新的认识.所以把书上的知识点做下笔记,以便以后复习使用. 并发与并行 仔细说来, ...
- java 多线程——并发编程模型 学习笔记
并发编程模型 ...
- 《Java并发编程的艺术》第4章 Java并发编程基础 ——学习笔记
参考https://www.cnblogs.com/lilinzhiyu/p/8086235.html 4.1 线程简介 进程:操作系统在运行一个程序时,会为其创建一个进程. 线程:是进程的一个执行单 ...
- java高并发编程(一)
读马士兵java高并发编程,引用他的代码,做个记录. 一.分析下面程序输出: /** * 分析一下这个程序的输出 * @author mashibing */ package yxxy.c_005; ...
- Java 面试知识点解析(二)——高并发编程篇
前言: 在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Java 知识点进行复习和学习一番,大 ...
- Java 多线程高并发编程 笔记(一)
本篇文章主要是总结Java多线程/高并发编程的知识点,由浅入深,仅作自己的学习笔记,部分侵删. 一 . 基础知识点 1. 进程于线程的概念 2.线程创建的两种方式 注:public void run( ...
- [ 高并发]Java高并发编程系列第二篇--线程同步
高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...
- java线程高并发编程
java线程具体解释及高并发编程庖丁解牛 线程概述: 祖宗: 说起java高并发编程,就不得不提起一位老先生Doug Lea,这位老先生可不得了.看看百度百科对他的评价,一点也不为过: 假设IT的历史 ...
随机推荐
- Web browser发展演变
浏览器是指可以显示网页服务器或者文件系统的HTML文件内容,并让用户与这些文件交互的一种软件.网页浏览器主要通过HTTP协议与网页服务器交互并获取网页,这些网页由URL指定,文件格式通常为HTML.大 ...
- 【redux】详解react/redux的服务端渲染:页面性能与SEO
亟待解决的疑问 为什么服务端渲染首屏渲染快?(对比客户端首屏渲染) react客户端渲染的一大痛点就是首屏渲染速度慢问题,因为react是一个单页面应用,大多数的资源需要在首次渲染前就加载 ...
- 从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路
本文原作者阮一峰,作者博客:ruanyifeng.com. 1.引言 HTTP 协议是最重要的互联网基础协议之一,它从最初的仅为浏览网页的目的进化到现在,已经是短连接通信的事实工业标准,最新版本 HT ...
- 几分钟几张图教你学会如何使用UML
很多初次接触UML的朋友们可能会感觉它各种各样的线条.关系.描述等晦涩难懂.本篇文章简单介绍了一下其中几个图,用最朴实的语言结合上图片来让你一眼就能理解他们,如果您在阅读的过程种发现错误之处恳请您在评 ...
- Java核心技术卷一基础知识-第14章-多线程-读书笔记
第 14 章 多线程 本章内容: * 什么是线程 * 中断线程 * 线程状态 * 线程属性 * 同步 * 阻塞队列 * 线程安全的集合 * Collable与Future * 执行器 * 同步器 * ...
- [Swift]Xcode标记:MARK、TODO、FIXME
1. MARK MARK一定要大写.其又叫做代码标注,我们可以使用它来添加一些说明文字.同时可以选择其上方是否需要显示分割线. // MARK: - 说明文字,带分割线 // MARK: 说明文字,不 ...
- lua入门demo(HelloWorld+redis读取)
1. lua入门demo 1.1. 入门之Hello World!! 由于我习惯用docker安装各种软件,这次的lua脚本也是运行在docker容器上 openresty是nginx+lua的各种模 ...
- Netty Decoder:ByteToMessageDecoder
1. ByteToMessageDecoder 这个类是解码器的基类,其中描述了解码器基本的工作方式和实现原理::还定义了一个解码的抽象方法decode,这个方法由业务实现,负责将一段字节数据解码为具 ...
- java中的正则表达式捕获组与引用的概念
今天群里有个人问,怎样用增则表达式匹配三角形的三边,其实只是要匹配三个数字而已,如 301 402 503 开始认为很简单,我就写了一个 "(([1-9]\\d?)\\s){2}$2&q ...
- wamp解决ajax跨域问题
若使用ajax测试本地数据时,遇到的跨域问题,如 因为ajax只能用于请求服务器的数据,而在本地测试,打开的文件是以 file:// 的形式, 所以报错 可以通过 nginx 建立反向代理,处理静态文 ...