一.原因
java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证了该变量的唯一性和准确性。
二.线程同步的方式
1.监视器(锁)synchronized关键字
线程可以成为此对象监视器的所有者:
1)通过执行此对象的同步 (Sychronized) 实例方法。
2)通过执行在此对象上进行同步的 synchronized 语句的正文。
3)对于 Class 类型的对象,可以通过执行该类的同步静态方法。
可以修饰对象,方法,用法:
1)修饰一个代码块,被修饰的代码块称为同步代码块,作用范围是大括号{}括起来的代码;
2)修饰一个方法,被修饰的方法称为同步方法,其作用范围是整个方法;
3)修饰一个静态方法,作用范围是整个静态方法;
4)修饰一个类,作用范围是synchronized后面括号括起来的部分。
如下:
共享资源:电话
public class Tel {
//打电话
public void call(){
for (int i = 0; i <10 ; i++) {
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}
/* public synchronized void call(){
for (int i = 0; i <10 ; i++) {
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}*/
/* public void call(){
for (int i = 0; i <10 ; i++) {
System.out.println(Thread.currentThread().getName()+"--->"+i);
}
}*/
/*public void call(){
synchronized (this) {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "--->" + i);
}
}
}*/
}
多人共享一个电话
public class Person extends Thread {
Tel tel ;
public Person(String name,Tel tel){
super(name);
this.tel = tel;
}
/* @Override
public void run() {
synchronized (tel){
tel.call();
}
}*/
@Override
public void run() {
tel.call();
}
public static void main(String[] args) {
Tel tel = new Tel();
Person p1 = new Person("yy",tel);
p1.start();
Person p2 = new Person("dl",tel);
p2.start();
Person p3 = new Person("bc",tel);
p3.start();
}
}
2.使用特殊域变量(volatile)实现线程同步
3.使用重入锁实现线程同步
ReentrantLock() : 创建一个ReentrantLock实例
lock() : 获得锁
unlock() : 释放锁