单例多线程中,举例说明synchronized关键字和volatile关键字的差别

synchronized属于对象锁可以保证多线程的安全,但是会造成阻塞比较严重。即使对synchronized进行优化,也会留有一定的阻塞,对计算机的性能不太友好。

volatile关键字相当于内存和cpu之间的放哨员,如果有synchronized修饰的变量a,在多线程同时访问变量a并进行修改成b时,如果有某个线程已经把a改为b了,就会返回给内存,并提醒其他核的cpu:“变量a已改,无需再改”。

volatile实例

package practice;

    //volatile关键字作用(修饰类中属性)
	//1.保证线程的可见性()
	//2.禁止指令重排序
	//3.但不能保证其原子性

class Singleton06{
public Singleton06() {
	System.out.println("instance");
}
//volatile不能修饰方法一般都是修饰变量属性
private static volatile Singleton06 instance ;
public static Singleton06 getInstance() {
	if (instance==null) {
		instance = new Singleton06();
		}
	return instance;
	}
}

public class TestObjectInstance_practice {
	public static void main(String[] args) {
		//记录当前时间
		long a=System.currentTimeMillis();
		//执行多线程访问
		doTestManyThread();
		//输出执行时间
		System.out.println("\r<br>执行耗时 : "+
				(System.currentTimeMillis()-a)/1000f+" 秒 ");
	}

	private static void doTestManyThread() {
		class Task implements Runnable {
			@Override
			public void run() {
				Singleton06.getInstance();
				
			}
		}
        //调用一千个线程访问获取instance变量
		for (int i = 0; i <1000; i++) {
			new Thread(new Task()).start();
			
		}
	}
}

运行结果:

synchronized例子:

package practices;

//synchronized 保证代码的原子性(不能同时有多个线程在这代码)
//synchronized 要让多个线程在这个代码块上顺序执行
//此设计虽然保证了线程安全,性能却大大减低
//重构方法的设计,优化synchronized(既要保证线程的安全,又减少阻塞)但是在高并发中阻塞依然明显

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

public class TestObjectInstance_practice {
	public static void main(String[] args) {
		//记录当前时间
		long a=System.currentTimeMillis();
		//执行多线程访问
		doTestManyThread();
		//输出执行时间
		System.out.println("\r<br>执行耗时 : "+
				(System.currentTimeMillis()-a)/1000f+" 秒 ");
	}

	private static void doTestManyThread() {
		class Task implements Runnable {
			@Override
			public void run() {
				Singleton03.getInstance();
				
			}
		}
		for (int i = 0; i <1000; i++) {
			new Thread(new Task()).start();
			
		}
	}
}

运行结果:

从两个运行结果可以看出,

volatile修饰后,创建了三个对象,所以没有确保原子性,但是运行时间却比synchronized少很多。

synchronized的运行结果,只创建一个instance对象,可以确保原子性,但是运行时间却比volatile长,造成一定的阻塞。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值