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();
}
}

复制代码

 

原文地址:https://www.cnblogs.com/dddyyy/p/9965836.html
posted @ 2019-06-08 21:09  星朝  阅读(1047)  评论(0)    收藏  举报