Java-线程同步机制(synchronized关键字)
- 线程同步:在多线程编程中,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证:数据在任何时刻,最多有一个线程访问,以保证数据的完整性。
- 理解:即当有一个线程在对某个内存地址进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作。
线程同步的实现方法(synchronized关键字)
1.同步代码块
synchronized (对象){//得到对象的锁,才能操作同步代码
//需要被同步的代码
}
2.同步方法
- synchronized关键字放在方法的声明中,表示整个方法为同步方法
//例如:
public synchronized void func(String name){
//需要被同步的代码
}
- 以售票为例:
//使用synchronized关键字实现线程同步
class SellTicket_Runnable implements Runnable{
private int tickets = 200;//共享变量
private boolean loop = true;
public synchronized void sell(){//使用了synchronized关键字后,不会超卖了;
if(tickets <= 0) {
System.out.println("卖完了。。。");
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "卖了一张票,余票:" + (--tickets));
}
@Override
public void run() {
while(loop){
sell();
}
}
}
public class Thread_synchronized02_SellTicket {
public static void main(String[] args) {
SellTicket_Runnable sellTicket_runnable = new SellTicket_Runnable();
Thread thread1 = new Thread(sellTicket_runnable);
Thread thread2 = new Thread(sellTicket_runnable);
thread1.start();//1
thread2.start();//2
}
}
同步原理
互斥锁
-
1.Java语言中,引入互斥锁来保证共享数据操作的完整性。
-
2.每一个对象都都对应一个可称为“互斥锁”的标记,这个标记用来保证:在任一时刻,只有一个线程能够访问该对象。
-
3.关键字synchronized与互斥锁之间的联系:当某个对象使用synchronized关键字修饰时,表明该对象在任一时刻只能有一个线程访问。
-
4.同步的局限性:导致程序的执行效率降低;
-
5.同步方法的锁:
-
若该方法是静态的,则锁默认加在当前类.class;
-
若该方法是非静态的,则锁加在this上,也可以加在其他对象上,但是多个线程”争夺的锁“必须是同一个对象的锁(这句结合案例代码理解):
-
SellTicket_Runnable sellTicket_runnable = new SellTicket_Runnable();
-
-
-
6.也可以在代码块上加锁;
//案例:售票
class SellTicket_Runnable implements Runnable{
private int tickets = 200;//共享变量
private boolean loop = true;
private final Object object = new Object();
public /*synchronized*/ void sell(){
//1.使用了synchronized关键字后,不会超卖了;
//2.在同一时刻,只有一个线程能够执行sell()方法;
//3.public synchronized void sell()是一个同步方法,锁加在this上
//4.也可以不在方法上写synchronized,写在代码块也可以;
// synchronized (this){//同步代码块,锁加在this上;
synchronized (object){//也可以加在其他对象上,多个线程需要获得同一个对象(即object对象)的锁;
if (tickets <= 0) {
System.out.println("卖完了。。。");
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName() + "卖了一张票,余票:" + (--tickets));
}
}
//给静态代码块加锁
public static void m1(){
//synchronized (this){//报错,静态代码块默认锁对象是:当前类.class;
synchronized (SellTicket_Runnable.class){
System.out.println("静态代码块");
}
}
@Override
public void run() {
while(loop){
sell();
}
}
}
public class Thread_synchronized02_SellTicket {
public static void main(String[] args) {
SellTicket_Runnable sellTicket_runnable = new SellTicket_Runnable();
Thread thread1 = new Thread(sellTicket_runnable);
Thread thread2 = new Thread(sellTicket_runnable);
thread1.start();//线程1
thread2.start();//线程2
}
}