课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
我们在前几期的文章中给大家简单介绍了java编程线程与进程的一些基础知识等内容,下面我们就一起来了解一下,java编程线程安全问题与解决方法。
什么是线程安全?
当多个线程去访问同一个类(对象或方法)的时候,该类都能表现出一致的行为,没有意想不到的不同结果,那我们就可以说这个类是线程安全的。
造成线程安全问题的主要诱因有两点:
一是存在共享数据(也称临界资源)
二是存在多条线程共同操作共享数据
为了解决这个问题,当存在多个线程操作共享数据时,需要保证同一时刻有且只有一个线程在操作共享数据,这种方式有个高尚的名称叫互斥锁,在Java中,关键字synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时我们还应该注意到synchronized另外一个重要的作用,synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代volatile功能)
锁的互斥性表现在线程尝试获取的是否是同一个锁,相同类型不同实例的对象锁不互斥,而class类对象的锁与实例锁之间也不互斥。
synchronized主要有3种使用方式
修饰实例方法,作用于当前实例,进入同步代码前需要先获取实例的锁
修饰静态方法,作用于类的Class对象,进入修饰的静态方法前需要先获取类的Class对象的锁
修饰代码块,需要指定加锁对象(记做lockobj),在进入同步代码块前需要先获取lockobj的锁
synchronized作用于实例对象
synchronize作用于实例方法需要注意:
实例方法上加synchronized,线程安全的前提是,多个线程操作的是同一个实例,如果多个线程作用于不同的实例,那么线程安全是无法保证的
同一个实例的多个实例方法上有synchronized,这些方法都是互斥的,同一时间只允许一个线程操作同一个实例的其中的一个synchronized方法
synchronized作用于静态方法
当synchronized作用于静态方法时,锁的对象就是当前类的Class对象。
synchronized同步代码块
方法体可能比较大,同时存在一些比较耗时的操作,而需要同步的代码又只有一小部分时使用。加锁时可以使用自定义的对象作为锁,也可以使用this对象(代表当前实例)或者当前类的class对象作为锁。
疑问:
Q:synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代volatile功能),synchronized是怎么保证可见性的呢?
Java原子操作要求lock和unlock操作时必须做到可见性,即对主内存的副本工作内存做修改时会马上回写主内存;还有就是读取工作内存副本数据时每次都会读主内存新的数据。
Q:同一个实例的多个实例方法上有synchronized,这些方法都是互斥的,同一时间只允许一个线程操作同一个实例的其中的一个synchronized方法.验证同一时间只允许一个线程操作同一个实例的其中的一个synchronized方法是对的。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。