Java-初步认识-第十三章-验证静态同步函数的锁

一.

接下来更加深入地讲解一下,示例还是卖票,但是程序稍作了修改。

也就是调用的同步函数有多个修饰符,有了static的存在。

由于show函数是静态的,访问的num,那么num也要修改为静态的变量。其实num静不静态都一样,都是共享数据。

在加了两个静态修饰符后,再次编译运行一下程序。

DOS结果显示又出现了安全问题。为啥?就是验证一点,静态同步函数用的锁绝对不是this,静态方法当中根本就没有this。

这不是我们要追究的问题,问题是用的不是this,用的是啥?

同步函数有所属的对象,叫做this,使用静态就没有所属对象了。函数一进内存的时候,有对象吗?锁肯定是对象。函数进内存有对象吗?有人说函数随着类的加载而加载,函数进内存哪来的对象?到底是用哪个对象啊?是说类进内存时,静态就在了,那这个类有对象吗?按照我们当初的理解叫做,这个类还没有通过new创建对象,但是java有个特点是,字节码文件进内存是先封装对象。这个对象在哪儿讲过呢?之前我们说过,所有的对象建立它们都有自己的字节码文件对象,用getclass方法获取的。是的,就是这个对象,一进内存就有对象,这个对象就是当前class文件所属的对象。这个就是同步静态函数所使用的锁,因为只有这么一个。

该如何表示呢?有的人采用下面的格式。从编译的结果来看,已经结束了,而且没有问题。但是和我们之前说的好像有些不一样。

通过This.gerClass()拿到的确实是当前字节码文件的对象。我们来验证一下,

下图的t.getClass()获取的就是当前字节码文件对象,下图写this.getClass(),这两个获取的是同一个。肯定是嘛,为什么?就算new出多个Ticket,这个getClass都是同一个。因为同一个类才产生很多对象。t和this指向同一个对象,拿过来的是同一个对象,

很多人觉着这种方式看着变扭,可以换一种方式,之所以这么写,是因为之前咱们学过getClass。其实字节码文件表达方式还有另外形式,下图就展现了两种。

任何一个类型都有一个属性,就是小写的class。这个属性就可以直接获取该字节码文件的对象。这两种方式都可以,Ticket.class比t.getClass()强在哪儿啊?它可以直接不用创建完对象调用方法,直接用类型点class属性就可以了。这就是我们说的两种表现方式,哪一种都可以。

你要是不愿意写this.getClass(),也可以写Ticket.class,这两种形式都可以。

编译运行也没有问题。

这两种方式都行,所以咱们总结一下,

早期卖票的例子,我们用的obj对象,如果不用obj,还可以用什么?用this也行,因为对象就一个,

如果不用这个,还可以用Ticket.class。其实对象是任意的,只要保证是唯一就行,只要保证多个线程用的是同一个锁就行。

类名.class(在静态中相当于对象)在内存中必须是唯一的,根据这唯一的字节码文件创建了n多的对象。

package test;
/**
 * @author 高小硕
 * 同步函数的使用的锁是this
 * 
 * 同步函数和同步代码块的区别:
 * 同步函数的锁是固定的this
 * 同步代码块的锁是任意的对象
 * 
 * 开发的时:
 * 建议使用同步代码块
 * 
 * 
 * 静态的同步函数使用的锁是  该函数所属字节码文件对象
 * 
 * 可以用getclass 方法获取  也可以用当前 类名.class 表示
 */
class Tickets implements Runnable {
	private static int num = 10;
	// Object obj = new Object();

	boolean flag = true;

	public void run() {
		
//		System.out.println("thisss:"+Tickets.class);

		if (flag)
			while (true) {
				//synchronized (this) ,静态函数下这个不行
				//synchronized (this.getClass()) 
				synchronized (Tickets.class) //建议这个

				{
					if (num > 0) {
						try {
							Thread.sleep(10);
						} catch (InterruptedException e) {
							// TODO: handle exception
						}

						System.out.println(Thread.currentThread().getName() + "..obj..." + num--);
					}

				}

			}
		else
			while (true)
				this.show();
	}

	// 同步函数
	public static synchronized void show() {
		
		if (num > 0) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO: handle exception
			}
			System.out.println(Thread.currentThread().getName() + "..function..." + num--);
		}
	}
}

class SynFunctionLockDemo {

	public static void main(String[] args) {
		Tickets t = new Tickets();// 创建一个线程任务对象
		
//		Class clazz = t.getClass();
//		
//		Class clazz1 = Tickets.class;
//		
//		System.out.println(clazz==clazz1);//true
	
		//System.out.println("t:"+t);
		Thread t1 = new Thread(t);
		Thread t2 = new Thread(t);
		// Thread t3 = new Thread(t);
		// Thread t4 = new Thread(t);

		t1.start();		
		
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			// TODO: handle exception
		}
		t.flag = false;
		t2.start();
		// t3.start();
		// t4.start();
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值