还不知道线程同步? 来来来….
什么叫同步?
同步(英语:Synchronization):指对在一个系统中所发生的事件之间进行协调,在时间上出现一致性与统一化的现象。
为什么要线程同步?
当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各个线程之间要有先来后到,不能一窝蜂同时挤上去抢作一团。
线程同步其实就是相对于现实中的“排队”,几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。
线程同步是为了防止多个线程同时访问同一个数据对象时,对数据造成破坏。
线程的同步是保证多线程安全访问资源的一种手段。
示例
例如: 这里模仿有6个人同时对同一个银行账户进行存款操作
代码:
|
|
|
|
测试代码
|
|
运行结果
很显然,上面的结果是错误的,导致错误的原因就是 多个线程 并发 访问了同一个竞争资源而引起的。
如何解决并发问题?
同步和锁
Java为此也提供了2种锁机制,synchronized 和 Lock.
关键字: synchronized
Java中每一个对象都有一个内置锁。
当程序运行到synchronized同步代码块时,自动获得锁定对象的锁。
一个对象只有一个锁。
所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放锁。
这也意味着任何其他线程都不能进入synchronized方法或代码块,直到该锁被释放。
Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。
Synchronized的作用主要有三个:
(1)确保线程互斥的访问同步代码
(2)保证共享变量的修改能够及时可见
(3)有效解决重排序问题。
从语法上讲,Synchronized总共有三种用法:
(1)修饰普通方法
(2)修饰静态方法
(3)修饰代码块
Java编程语言对 synchronized 提供了两种基本的同步用法: 同步方法 和 同步语句。
—— synchronized 同步方法
Synchronized 修饰一个方法很简单,就是在方法的前面加synchronized 关键字即可
synchronized关键字 放在 修饰符(如:public 等)之后,返回类型声明(如:void等)之前.
使用synchronized的方法(同步方法),即一次只能有一个线程进入该方法,其他线程要想在此时调用该方法,只能排队等候, 当前线程(就是在synchronized方法内部的线程)执行完该方法后,别的线程才能进入.
(一) 修饰普通方法
—示例代码(例如:修改之前账户类的存款方法)
|
|
——- 测试结果 ————————
使用线程同步以后,操作数据就正确了。
( 二 ) 修饰静态方法
示例代码如下
|
|
测试代码
|
|
——- 测试结果 ————————
注意对静态方法的同步本质上是对类的同步(静态方法本质上是属于类的方法,而不是对象上的方法),所以即使 oneObj 和 twoObj 属于不同的对象,但是它们都属于StaticSynchronizedMethod 类的实例,所以也只能顺序的执行testMethod方法,不能并发执行。
Synchronized 关键字 修饰普通方法 与 修饰静态方法 的区别
- synchronized 修饰静态方法是同步某个类的范围。
如 : synchronized static void testMethod()方法是防止多个线程中多个实例同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。
- synchronized 修饰普通方法是同步某个实例的范围。
如:public synchronized void save()方法( –存钱的方法–),防止多个线程中 对 同一个实例 同时访问这个对象的 synchronized 方法。
—— synchronized 同步块
通过 synchronized 关键字来声明 synchronized 块。语法如下
|
|
示例代码
|
|
测试代码
|
|
——- 测试结果 ————————
synchronized 方法 与 synchronized 代码块的区别
synchronized 方法 与synchronized 代码块 之间 没有什么区别,只是 synchronized 方法便于阅读理解,而synchronized 代码块 可以更精确的控制冲突限制访问区域,有时候表现更高效率。