java线程同步有几种方法,java如何实现多线程的同步

  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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: