首页 >> 大全

多线程-线程内存可见性-线程同步的单例模式

2023-12-21 大全 39 作者:考证青年

线程同步

可以修饰实例方法,也可以修饰静态方法,还可以修饰代码块,会为代码块加上内置锁,从而实现线程同步。

在静态方法中添加同步代码块。

修饰同步代码块,

(){

//

()内部需要设置加锁的资源,静态方法属于类的方法,不属于任何一个实例对象,所以静态方法中的()只能锁定类,不能锁定实例对象,this可以表示当前的一个实例。

实例方法中也可以使用关键字实现同步代码块。

先来个案例:

用多线程打印a1-b2-c3-d4-e5 ····· z26

-wait-小应用

写法一:


public class Class01 {private static Object obj = new Object();public static void main(String[] args) {Thread t1 = null, t2 = null;char[] c1 = "abcdefghijklmnopqrstuvwxyz".toCharArray();int[] c2 = new int[26];for (int i = 0; i < 26; i++) {c2[i] = i + 1;}t1 = new Thread(() -> {synchronized (obj) {for (int i = 0; i < c1.length; i++) {System.out.print(c1[i]);try {Thread.currentThread().sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}try {obj.notify();obj.wait();} catch (InterruptedException e) {e.printStackTrace();}obj.notify();}}}, "t1");t2 = new Thread(() -> {synchronized (obj) {for (int i = 0; i < c2.length; i++) {if (i == c2.length - 1) {System.out.print(c2[i]);} else {System.out.print(c2[i] + "-");}try {Thread.currentThread().sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}try {obj.notify();obj.wait();} catch (InterruptedException e) {e.printStackTrace();}obj.notify();}}}, "t2");if (c1.length == c2.length) {t1.start();t2.start();} else {System.out.println("c1.length 不等于 c2.length");}}
}

写法二:


import java.util.concurrent.locks.LockSupport;public class Class02 {// 1A-2B-3C-4Dstatic Thread t12 = null, t22 = null;public static void main(String[] args) {char[] c1 = "abcdefghijklmnopqrstuvwxyz".toCharArray();int[] c2 = new int[26];for (int i = 0; i < 26; i++) {c2[i] = i + 1;}t12 = new Thread(() -> {for (char i : c1) {System.out.print(i);LockSupport.unpark(t22);LockSupport.park();}}, "t1");t22 = new Thread(() -> {for (int i : c2) {LockSupport.park();if (i == c2[c2.length - 1]) {System.out.print(i);} else {System.out.print(i + "-");}LockSupport.unpark(t12);}}, "t2");if (c1.length == c2.length) {t12.start();t22.start();} else {System.out.println("c1.length 不等于 c2.length");}}
}

.class:获取的是在内存中的运行时类,每个运行时类只有一份。

package com.m.test;public class Class03 {public static void main(String[] args) {// 能同步MyRunnable03 myRunnable03 = new MyRunnable03();for (int i = 0; i < 5; i++) {Thread thread = new Thread(myRunnable03);thread.start();}}
}

public class MyRunnable03 implements Runnable {@Overridepublic void run() {//synchronized(MyRunnable03.class)synchronized(this) {System.out.println("start...");try {Thread.currentThread().sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end...");}}}

5个实例化对象

package com.m.test;public class Class01 {public static void main(String[] args) {//能同步for (int i = 0; i < 5; i++) {MyRunnable01 myRunnable01 = new MyRunnable01();Thread thread = new Thread(myRunnable01);thread.start();}}
}


public class MyRunnable01 implements Runnable {private static Integer num = 1;@Overridepublic void run() {
//		num++;synchronized (num) {System.out.println("start...");try {Thread.currentThread().sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end...");}}}

1个实例化对象

package com.m.test;public class Class02 {public static void main(String[] args) {// 不能同步MyRunnable02 myRunnable02 = new MyRunnable02();for (int i = 0; i < 5; i++) {Thread thread = new Thread(myRunnable02);thread.start();}}
}

public class MyRunnable02 implements Runnable {private static Integer num = 1;@Overridepublic void run() {
//		num++;	判断num是一个还是多个synchronized(num) {System.out.println("start...");try {Thread.currentThread().sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("end...");}}}

单例模式

整个系统中,无论做怎样的业务操作,保证内存中只有一个对象实例。

数据保存在主内存中的,线程在访问该数据时,并不是直接访问主内存中的数据,而是从主内存中拷贝一份数据出来放入工作内存,线程对工作内存中的数据进行操作,操作完成之后再将工作内存中的数据拷贝到主内存中。

使用关键字来解决因为工作内存-主内存机制导致可能会发生的单例的错误。

使用关键字修饰的变量,主内存对线程可见。

线程甲修改了其工作内存中的数据,线程乙工作内存中的数据会同步更新的。

为什么要用到工作内存?工作内存可以用到CPU的缓存,程序的效率更高。但是线程不安全的。

双重锁

package com.m.test;//断点调试:F5,6,7,8,
public class Class01 {public static void main(String[] args) {for (int i = 0; i < 5; i++) {new Thread(new Runnable() {@Overridepublic void run() {Singleton singleton = Singleton.getInstance();}}).start();;}}
}

public class Singleton {private volatile static Singleton singleton = null;private Singleton() {System.out.println("创建了Singleton对象");}public static Singleton getInstance() {if (singleton == null) {synchronized (Singleton.class) {if (singleton == null) {singleton = new Singleton();}}}return singleton;}
}

导致的死锁--01

package com.m.test;//断点调试:F5,6,7,8,
public class Class01 {public static void main(String[] args) {DeadLock d1 = new DeadLock();d1.flag = true;DeadLock d2 = new DeadLock();d2.flag = false;new Thread(d1,"杨三").start();new Thread(d2,"杨四").start();}
}

public class DeadLock implements Runnable {public boolean flag;private static Object o1 = new Object();private static Object o2 = new Object();@Overridepublic void run() {if (flag) {synchronized (o1) {System.out.println(Thread.currentThread().getName() + "拿到了筷子o1");try {Thread.currentThread().sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (o2) {System.out.println(Thread.currentThread().getName() + "拿到了筷子o2,可以吃饭了。");}}}else{synchronized (o2) {System.out.println(Thread.currentThread().getName() + "拿到了筷子o2");try {Thread.currentThread().sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (o1) {System.out.println(Thread.currentThread().getName() + "拿到了筷子o1,可以吃饭了。");}}}}
}

避免死锁

    new Thread(d1,"杨三").start();try {Thread.currentThread().sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}new Thread(d2,"杨四").start();

导致的死锁--02

package com.m.test;public class Class01 {static Thread t1 = null, t2 = null;public static void main(String[] args) {final Object o = new Object();final Object o2 = new Object();char[] c1 = "12345".toCharArray();char[] c2 = "abcde".toCharArray();t1 = new Thread(() -> {synchronized (o) {for (int i = 0; i < c1.length; i++) {System.out.print(c1[i]);try {Thread.sleep(1000);} catch (InterruptedException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}try {t2.join();} catch (InterruptedException e) {e.printStackTrace();}}}}, "t1");t2 = new Thread(() -> {synchronized (o2) {for (int i = 0; i < c2.length; i++) {System.out.print(c2[i]);try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}}}}, "t2");t1.start();t2.start();}
}

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了