synchronize的两种用法

本文深入解析Java中的同步机制,涵盖对象锁与类锁的概念、用法及实例代码。通过对比不同锁的应用场景,帮助读者理解如何有效利用锁来实现线程间的同步,避免并发问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念:

     1、对象锁

          包括方法锁(默认锁对象为this当前实例对象)和同步代码块锁(自己指定锁对象)

     2、类锁

          指定synchronize修饰静态的方法或指定锁为class对象

二、用法

     1、对象锁

          (1)同步代码块

package com.zy.san.synSan;

/**
 * 
 * 
 * @author Administrator 对象锁实例1,代码块形式
 */
public class SynchronizedObectCodeBlock2 implements Runnable {

	static SynchronizedObectCodeBlock2 instance = new SynchronizedObectCodeBlock2();

	public static void main(String[] args) throws InterruptedException {
		Thread th1 = new Thread(instance);
		Thread th2 = new Thread(instance);
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {
		}
		System.out.println("finished");
	}

	@Override
	public void run() {
		synchronized (this) {

			// Thread.currentThread()当前线程,.getName()名字
			System.out.println("我是对象锁的代码块形式我叫" + Thread.currentThread().getName());
			try {
				// 让线程休眠3秒
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println(Thread.currentThread().getName() + "运行结束");
		}
	}
}

 结合上面的代码猜猜看结果

可以看出它运行的顺序是一个对象运行完成后再运行的第二个对象

当我把synchronize注释掉后,两对象几乎是同时执行同时结束的,这就起不到保护的效果了。

               a、对象锁

     synchronize代码块使用的对象锁是this,如果遇到了非常复杂的业务逻辑是该怎么办了。

Object lock1=new Object();
	Object lock2=new Object();
	
	public void run() {
		synchronized (lock1) {

			// Thread.currentThread()当前线程,.getName()名字
			System.out.println("我是对象锁的代码块形式我叫" + Thread.currentThread().getName());
			try {
				// 让线程休眠3秒
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println(Thread.currentThread().getName() + "运行结束");
		}
		synchronized (lock2) {

			// Thread.currentThread()当前线程,.getName()名字
			System.out.println("我是对象锁的代码块形式我叫" + Thread.currentThread().getName());
			try {
				// 让线程休眠3秒
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			System.out.println(Thread.currentThread().getName() + "运行结束");
		}
	}

可以指定自定义对象锁

运行结果3-4行,是同时运行的。是因为它们使用的不是同一个锁对象,它们不会串运行而是并运行。

如果它们使用同一个对象锁了?

               (2)方法锁:只能是修饰普通方法,对象锁默认为this

package com.zy.san.synSan;
/**
 * 
 * 
 * @author Administrator
 *对象锁实例2   方法锁形式 
 */
public class SynchronizedObectMethod3 implements Runnable{
	static SynchronizedObectMethod3 intance=new SynchronizedObectMethod3();
	public static void main(String[] args) {
		Thread th1=new Thread(intance);
		Thread th2=new Thread(intance);
		th1.start();
		th2.start();
		while(th1.isAlive() || th2.isAlive()){
			System.out.println("finished");
		}

	}
	public void run() {
		method();
	}
	public synchronized void method(){
		System.out.println("我是对象锁的方法修饰符形式,我叫:"+Thread.currentThread().getName());
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"结束");
	}

}

运行结果:

          2、类锁

               (1)概念:Java类可能有很多个对象,但只有1个class对象。

                          a、只有一个class对象:java类可能会有很多个对象,但是只有1个class对象。

                          b、本质:所以所谓的类锁,不过是class对象的锁而已。

                          c、用法和效果:类锁只能在同一时刻被一个对象拥有

                (2)形式1:synchronize加在static方法上。

package com.zy.san.synSan;

/**
 * 
 * @author Administrator 类锁的第一种形式,static形式(在方法上的)
 */
public class SynchronizedClassStatic4 implements Runnable {
	static SynchronizedClassStatic4 instance1 = new SynchronizedClassStatic4();
	static SynchronizedClassStatic4 instance2 = new SynchronizedClassStatic4();

	public static void main(String[] args) {
		Thread th1 = new Thread(instance1);
		Thread th2 = new Thread(instance2);
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {

		}
		System.out.println("finished");
	}

	public void run() {
		method();
	}

public static synchronized void method(){
	System.out.println("我是类锁的第一种形式,static形式,我叫:"+Thread.currentThread().getName());
	try {
		Thread.sleep(3000);
	} catch (InterruptedException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	System.out.println(Thread.currentThread().getName()+"结束");
	}

}

执行结果:

这里最大的魔力就是static的运用,如果不使用static会出现什么情况了。

它就不会出现同步。

如果我在使用同步时是全局不止一个对象就要使用类锁的第一种形式static形式。

                (3)形式2:synchronize(*.class)代码块。

package com.zy.san.synSan;

/**
 * 
 * 
 * @author Administrator 我是类锁的第二种形式,synchronize(*.class)形式
 */
public class SynchronizeClassClass5 implements Runnable {
	static SynchronizeClassClass5 instanec = new SynchronizeClassClass5();
	static SynchronizeClassClass5 instanec2 = new SynchronizeClassClass5();

	public static void main(String[] args) {
		Thread th1 = new Thread(instanec);
		Thread th2 = new Thread(instanec2);
		th1.start();
		th2.start();
		while (th1.isAlive() || th2.isAlive()) {

		}
		System.out.println("finished");
	}

	@Override
	public void run() {
		method();

	}

	private void method() {
		synchronized (SynchronizeClassClass5.class) {
			System.out.println("我是类锁的第二种形式,synchronize(*.class),我叫" + Thread.currentThread().getName());
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"结束");
		}

	}

}

运行结果:

如果我将*.class改成this会如何了。

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值