线程的同步

本文详细介绍了Java中线程同步的实现方式,包括非静态同步方法和静态同步方法的使用,以及如何通过锁定机制来保证数据的一致性和线程安全。文章还探讨了线程阻塞的情况,并给出了何时需要进行同步的指导。

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

Java中的线程同步的实现用的是锁定。

Java中的每个对象都有一个内置锁,当这个对象有同步的方法代码时,这个内置锁才会起作用。

1.非静态同步方法

(1)当进入到同步的非静态方法时,我们获得一个当前正在执行的代码的类的实例--this实例的锁,因为一个对象只有一个锁,所以当一个线程获得该锁时,其它线程就不能获得锁,即其它线程不能进入同步代码,直到当前线程释放该锁,所谓的释放锁,就是退出了这个同步方法。 只能同步方法,不能同步变量或者类 每个对象只有一个锁
(2) 多个线程可以访问类的其它非同步方法
(3) 如果线程睡眠,它依然保持已有的锁不会释放
(4)一个线程可以获得多个锁 比如它进入一个同步方法,获得当前对象的锁,而这个方法内又调用了其它对象的同步方法,因此也获得了其它对象的锁 在一个对象上调用一个同步方法,这个同步方法内调用了其它同步方法,是允许的,JVM知道当前线程获得了对象的锁
(5)可以是同步块,因为同步代码影响性能

class test
{
public synchronized void doStuff()
{
System.out.println("hello");
}
}

它等价于:

class test
{
public void doStuff()
{
synchronized(this) {
System.out.println("hello");
}
}
}

这个例子有点特殊,这两段代码完全没有区别,性能也一样,但实际中代码块中可以不同步那些不需要锁定的变量

2.静态的同步方法

静态数据在类中只有一个拷贝,所以需要一个用于整个类的锁。是有这样的一个锁的,Java中装载每个类都有一个代表着该类的java.lang.class实例,使用这个实例的锁来保护该类的静态方法

可以这样写:

public static synchronized void doStuff()
{
System.out.println("hello");
}


也可以用代码块:

public static void doStuff()
{
synchronized(test.class) {//test 是这个静态方法的类名
System.out.println("hello");
}
}

这个代码块可以写成下面这个比较长的形式:

public static void doStuff()
{
Class cl=Class.forName("test");
synchronized(cl) {
System.out.println("hello");
}
}



线程的阻塞:
1.使用相同实例调用同一个类中的非静态同步方法的线程将彼此阻塞,原因是它们都在这个实例上加了锁。但是如果它们使用了两个不同的实例进行调用,则它们获得两个锁,且这两个锁互不相关
2.调用静态同步方法的线程始终彼此阻塞
3.静态同步方法和非静态同步方法互不影响
4.同步块,要看看synchronized后面跟的是什么对象,在同一个对象上进行的同步线程彼此阻塞,在不同对象上则不会

何时需要同步:
局部变量不需要,因为每个线程都有一个副本,它们互不干扰
我们需要考虑的是静态字段和非静态字段

有些类被标为线程安全的类,比如StringBuffer,它只是在自己的某些方法上是线程安全的,但这不足以保证在执行过程中线程安全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值