线程间的互斥通信

本文深入探讨了Java中的Synchronized关键字,包括其如何控制类成员变量的访问、锁的机制及使用方式,同时介绍了线程间通信的基本原理,如wait()和notify()方法的应用。通过示例代码展示了如何利用这些特性来解决多线程并发问题。

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

Synchornized

1.用来控制对类成员变量的访问: 每个类实力都对应一把锁,每个Synchornized方法都必须获得调用该方法的类实例的所才可以进行执行,否则所属线程阻塞,方法一旦执行,则独占该锁,直到该方法执行完毕,其他线程才能获取该锁。这种机制保证了同一时刻对于每一个类的实例。其所有生命为Synchornized的成员方法之多只有一个处于执行状态,因为只有一个可以获取该实例对应的锁,从而可以避免类成员的访问冲突(只有Synchornized修饰的方法才遵守这个规则)。
在java中,类和类实例(对象)都有一把锁。
代码段的同步获取的是显式声明的对象的锁。
修饰非静态方法的时候,获取的是调用该方法的对象的锁。
修饰静态方法时,获取的时该类的字节码文件,也就是class类的锁。

通信

主要通过Object的wait()和notify()方法进行实现。
wait方法,当前线程必须拥有此对象的锁。该线程发布对该对象的锁的拥有权,并等待执行,知道其他线程通过notify方法或notifyAll方法通知才此对象的监视器上等待的线程醒来。然后该线程等到重新获得对监视器的所有权后才能继续执行。线程通过调用wait()方法,在对象的监视器上等待。
notify方法,唤醒再次对象监视器上等待的单个线程。如果多个线程在此对象上等待,则会选择唤醒其中的一个,选择时任意性的,并在对实现做出决定时发生。

总结

多线程编程时,尽量将同步放在类的内部完成,而不是通过线程来进行同步,这样可以简化编程难度。
在Synchornized方法内部通过while()增加一次判断,增加程序的严谨性。因为在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒。

package com.cyan.synchornized;

/**
 * @description: 先执行sub,初次进入的时候,标志位true,所以直接打印下面的sub打印。当然再次过程中还会执行main,但是会执行main的wait。
 *                  当sub打印完成,则会将标志置为false.  此时当sub执行时,会进行阻塞,所以会使main()打印
 */
public class SynchornizedDamo {
    public static void main(String[] args) {
        final  Business business = new Business();
        new Thread(new Runnable(){
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    business.sub(i);
                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 50; i++) {
                    business.main(i);
                }
            }
        }).start();
    }
}
/**
*@Description:  解决多线程问题时,尽量将线程同步放在类中解决,而不是在多线程中同步
*/
class Business{
    private boolean isRunning = true;
    public synchronized void sub(int n) {
        while (!isRunning) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (int i = 0; i < 10; i++) {
            System.out.println("sub:" + i + "   loop of :" + n);
        }
        isRunning = false;
        this.notify();
    }
    public synchronized void main(int n) {
        while (isRunning) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (int i = 0; i < 100; i++) {
            System.out.println("main : " + i + "    loop of: "  + n);
        }
        isRunning = true;
        this.notify();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值