1.同一个资源,同步和非同步的方法可以同时调用

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

public classY {public synchronized voidm1() {

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 voidmain(String[] args) {

Y t= newY();//new Thread(()->t.m1(),"t1").start();//new Thread(()->t.m2(),"t2").start();

new Thread(newRunnable() {

@Override

public void run() {

t.m1();

}

},"t1").start();;

new Thread(new Runnable() {

@Override

public void run() {

t.m2();

}

},"t2").start();;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

2bf80e80a3879f38d9eca07035fc45fc.png

可以看到t1先执行,如果不能同时调用那么t2是不能执行的,必须等t1结束,释放锁后才能调用,但这里t2确先执行了,所以是可以同时调用的。

2.对业务写代码进行加锁,对读代码不进行加锁,会产生脏读

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

public classU {privateString name;private doublebanlance;

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

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

670c21c904673f3cffc46e30ac5c137d.png

3.同线程内一个同步方法可以去调用另一个同步方法(重入锁 还有一种重入锁就是子类调用父类的同步方法)

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

public classI {public synchronized voidm1() {

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

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

e6c480d924c5e92631e85cd110dc1d04.png

4.模拟一个简单的死锁

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

public classDeadLock {private Object o1 = newObject();private Object o2 = newObject();

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

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

5.如果执行同步方法中出现异常,那么就会自动释放锁,如果不想释放锁,加上try catch

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

public classReleaseLock {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();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

fbe555b7c70540437089c5538551219a.png

6.volatile关键字(无锁同步)

volatile关键字 每个线程都有自己的一小块内存,执行的时候会把变量copy过来,修改了后在写回对象,

执行m1方法的线程把 running读到内存里,与此同时主线程也把running读到内存,并进行修改,写回对象为false

但是执行m1的线程里的内存一直都是true啊(因为太忙了没空去刷新)所以会形成死循环,

volatile就是当running改了之后 *立马去通知其他线程,你们记得去主存刷新一下,一刷新,running为false,退出while循环。

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;/*** volatile关键字 每个线程都有自己的一小块内存,执行的时候会把变量copy过来,修改了后在写回对象,

* 执行m1方法的线程把 running读到内存里,与此同时主线程也把running读到内存,并进行修改,写回对象为false

* 但是执行m1的线程里的内存一直都是true啊(因为太忙了没空去刷新)所以会形成死循环,volatile就是当running改了之后

* 立马去通知其他线程,你们记得去主存刷新一下,一刷新,running为false,退出while循环。

*@authordingyu

**/

public classVolatileDemo {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;

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

7.voliatile 不能保证原子性 不能替换synchronized

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

/**

voliatile 不能保证原子性 不能替换synchronized

@authordingyu

*/

public classVolatileDemo02 {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);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

c728ccecd292c43413e21039bf9f10af.png

8.多个原子类的方法之间不具备原子性

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

importjava.util.concurrent.atomic.AtomicInteger;

/**

原子类 具有原子性,但两个原子类的方法之间不具备原子性

@authordingyu

*/

public classAtomicDemo {private AtomicInteger count = newAtomicInteger();

public void m1() {

for (int i = 0; i < 100; i++) {

count.incrementAndGet();

//两个原子类的方法之间不具备原子性

count.incrementAndGet();

}

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

9.原子类的不具备可见性

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

importjava.util.concurrent.atomic.AtomicBoolean;

public classAtomicDemo02 {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);

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

10.锁是锁在堆内存的那个对象上,而不是引用

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;

/**

锁是锁在堆内存的那个对象上,而不是引用

@authordingyu

*/

public classChangeReference {public Object o = newObject();

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

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

23a0c86890e6e69ccfe856bd906bd175.png

11.不要锁字符串常量

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu;/*** 不要锁字符串常量

*@authordingyu

**/

public classSynchronizedString {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();

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

12.wait 让线程暂停,释放锁, notify 唤醒线程,不释放锁

48304ba5e6f9fe08f3fa1abda7d326ab.png

packagecom.dingyu2;

/**

wait 让线程暂停,释放锁, notify 唤醒线程,不释放锁

@authordingyu

*/

public classWaitAndNotyifyDemo {private volatile int count = 0;private Object lock = newObject();

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

}

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐