java线程同步有几种方法,java如何实现多线程的同步
方法一:使用synchronized关键字
由于java中的每个对象都有一个内置锁,所以当用这个关键字装饰一个方法时,内置锁会保护整个方法。在调用这个方法之前,需要获取内置锁,否则会被阻塞。
注意:synchronized关键字也可以修改静态方法,如果静态方法被调用,整个类都会被锁定。
注意:同步是一项开销很大的操作,因此应该尽量减少同步的内容。通常不需要同步整个方法,只需要使用同步的代码块来同步关键代码即可。
Synchronized关键字用于保护共享数据。请注意“共享数据”。您必须区分哪些数据是共享数据。
相关视频教程推荐:java视频
示例:
包com . gcc . interview . synchro;
公共类MybanRunnable实现Runnable{
私人银行银行;
public MybanRunnable(银行bank) {
this.bank=bank
}
@覆盖
公共无效运行(){
for(int I=0;i10i ) {
bank . save 1(100);
System.out.println(账户余额为- bank . get account());
}
}
}包com . gcc . interview . synchro;
银行类别{
private int account=100
public int getAccount() {
返回帐户;
}
//同步方法
公共同步void save(int money) {
账户=钱;
}
公共void save1(int money) {
//同步代码块
同步(这){
账户=钱;
}
}
public void userThread() {
Bank Bank=new Bank();
MybanRunnable my1=new MybanRunnable(bank);
System.out.println(“线程1”);
线程th1=新线程(my1);
TH1 . start();
system . out . println(“Thread 2”);
线程th2=新线程(my1);
TH2 . start();
}
}方法二:wait和notify
Wait():让一个线程等待并释放被持有对象的锁。
Sleep():这是一个静态方法,用于将正在运行的线程置于睡眠状态。调用此方法来捕获InterruptedException。
Notify():唤醒一个等待的线程。注意,当这个方法被调用时,它不能准确地唤醒一个正在等待的线程,而是由JVM决定唤醒哪个线程,并且它不在优先级中。
Allnotity():唤醒所有处于等待状态的线程。注意,不是给所有被唤醒的线程一个对象锁,而是允许它们竞争。
方法三:使用特殊域变量volatile实现线程同步
A.volatile关键字为访问域变量提供了一种无锁机制。
B.用volatile修改域相当于告诉虚拟机,这个域可能会被其他线程更新。
C.因此,每次使用该域时都需要重新计算,而不是使用寄存器中的值。
D.volatile不提供任何原子操作,也不能用来修改final类型的变量。
例如:
在上面的例子中,只需在account前面添加volatile修饰就可以实现线程同步。
//只给出要修改的代码,其余代码同上。
银行类别{
//需要同步的变量加上volatile
私有易变int账户=100;
public int getAccount() {
返回帐户;
}
//这里不再需要同步
公共void save(int money) {
账户=钱;
}
}注意:多线程中的异步问题主要发生在读写域的时候。如果域本身避免了这个问题,就没有必要修改操作域的方法。通过最终域、锁保护域和可变域,可以避免异步问题。
方法四:使用重入锁实现线程同步
在JavaSE5.0中,添加了一个新的java.util.concurrent包来支持同步。
ReentrantLock类是一个可重入的互斥锁,它实现了锁接口。它具有与使用synchronized方法和fast相同的基本行为和语义,并扩展了它的功能。
ReenreantLock类的常用方法有:
如何解决写爬虫IP受阻的问题?立即使用。
注意:ReentrantLock()也有一个构造方法,可以创建一个公平锁,但是不推荐使用,因为这样会大大降低程序的运行效率。
private int account=100
private reentrant lock lock=new reentrant lock();
public int getAccount() {
返回帐户;
}
//同步方法
公共void save(int money) {
lock . lock();
尝试{
账户=钱;
}最后{
lock . unlock();
}
}注意:关于锁对象和同步关键字的选择:
A.最好两个都不用。使用java.util.concurrent package提供的机制,可以帮助用户处理所有与锁相关的代码。
B.如果synchronized关键字可以满足用户的需求,就使用synchronized,因为它可以简化代码。
C.如果需要更高级的函数,请使用ReentrantLock类。这个时候要注意及时释放锁,否则会出现死锁。通常,锁在finally代码中被释放。
方法五:使用局部变量来实现线程同步
如果使用ThreadLocal来管理变量,那么每个使用该变量的线程都会得到该变量的一个副本,并且这些副本是相互独立的,这样每个线程都可以随意修改自己的变量副本,而不会影响到其他线程。
ThreadLocal类的常用方法
//只改变银行类,其他代码同上。
公共类银行{
//使用ThreadLocal类管理共享变量帐户
私有静态thread local integer account=new thread local integer(){
@覆盖
受保护的整数initialValue(){
返回100;
}
};
公共void save(int money){
account . set(account . get()money);
}
public int getAccount(){
返回account . get();
}
}注意:ThreadLocal和同步机制
A.ThreadLocal和同步机制都是用来解决多线程中同一个变量的访问冲突。
B.前者采用‘空间换时间’的方法,后者采用‘时间换空间’的方法。
推荐文章教程:java零基础入门以上是如何在java中实现线程同步的详细内容。更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。