深入理解Java中的对象锁:同步与异步的选择与应用

目录

前言

一、什么是对象锁?

二、同步和异步

三、 同步代码块和同步方法

四、异步方法

五、Demo讲解


前言

        在多线程编程中,正确处理并发访问是确保程序正确性的关键。对象锁(Object Lock)是Java中常用的同步机制之一,用于防止多个线程同时访问共享资源。本文将详细讨论对象锁的同步和异步,以及如何在实际应用中有效地使用它们。

一、什么是对象锁?

        对象锁是基于对象实例的锁机制。在Java中,每个对象都有一个关联的监视器(monitor),当一个线程请求一个对象的锁时,它会尝试获得该对象的监视器。如果监视器被其他线程持有,则该线程进入阻塞状态,直到监视器被释放。

二、同步和异步

同步(Synchronous)意味着代码片段或方法在同一时间只能被一个线程执行。同步保证了多个线程对共享资源的互斥访问,从而避免数据不一致的问题。

异步(Asynchronous)意味着代码片段或方法可以被多个线程同时执行,不进行任何同步控制。这虽然提高了并行度,但也可能导致竞态条件和数据不一致的问题。

区别:同步是加了synchronized的,需要按顺序排队访问,而异步(加asynchronized/没有)是多个线程可以同时访问

三、 同步代码块和同步方法

在Java中,可以使用synchronized关键字来实现同步。我们可以将synchronized关键字用于方法或者代码块。

同步方法

public class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public synchronized int getCount() {
        return count;
    }
}

注:incrementgetCount方法是同步方法,意味着在同一时刻只能有一个线程访问这些方法。

同步代码块

public class Counter {
    private int count = 0;
    private final Object lock = new Object();

    public void increment() {
        synchronized (lock) {
            count++;
        }
    }

    public int getCount() {
        synchronized (lock) {
            return count;
        }
    }
}

四、异步方法

异步方法没有任何同步控制,多个线程可以同时访问:

public class Counter {
    private int count = 0;

    public void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}

注:如果多个线程同时调用increment方法,可能会导致count的值不准确,因为多个线程可能会同时读取和写入该变量。

五、Demo讲解

package com.ctb.demo;

/**
 * 对象锁的同步和异步问题
 * 
 * @author biao
 *
 * 2024年2月28日-下午2:08:32
 */
public class MyThraed3 {
	
	/**
	 * 加锁synchronized
	 */
	public synchronized void method1() {
		try {
			System.out.println(Thread.currentThread().getName());
			Thread.sleep(3000);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	/**
	 * 未加synchronized
	 */
	public void method2() {
		
		System.out.println(Thread.currentThread().getName());
		
	}
	
	public static void main(String[] args) {
		
	final MyThraed3 m = new MyThraed3();
		
		/**
		 * t1线程先持有object对象的lock锁,t2线程可以以异步的方式调用对象中的非synchronized修饰的方法
		 * t1线程先持有object对象的lock锁,t2线程如果在这个时候调用对象中的同步(synchronized)方法则需等待,也就是同步
		 */
		Thread t1 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				m.method1();
				
			}
		},"t1"); 
		Thread t2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				m.method2();
				
			}
		},"t2"); 
		
		t1.start();
		t2.start();
		
	}

}
/**
	 * 加synchronized
	 */
	public synchronized void method2() {
		
		System.out.println(Thread.currentThread().getName());
		
	}

注:注:在method2方法中未加synchronized,它则会同时打印(t1 t2),若加上锁,它打印t1后需等待3s再打印t2

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值