线程同步&线程池
Posted auge
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程同步&线程池相关的知识,希望对你有一定的参考价值。
线程同步&线程池
线程同步
线程不同步会出现的问题:
- 当多个线程操作同一资源时,会出现重复操作和和操作不存在的资源的问题,为了规避这一问题就需要线程的同步操作来实现资源的共同使用。
线程同步:
- 当多个线程操作同一资源时,给操作该资源的代码加上一把锁,当有一个线程拿到这把锁后,其他线程都不能操作带锁的资源代码,直至拿到锁的线程释放锁。
线程同步实现的3种方式:
同步代码块
synchornized(obj){
//涉及操作同一资源的代码
}
注: 没有静态的同步代码块
obj: 任意类型的对象,相当于一把锁,操作同一资源的而线程必须使用同一把锁。
如何保证多个线程使用同一把锁?
在设置线程任务,即定义线程对象时在成员变量的位置上声明一个对象,将声明的变量放在sychornized代码块中
/**
模拟买票功能,开启多个线程,同时买一百张票
/
public class SaleTicket implements Runnable{
/
不同对象使用同一个变量
/
private static int ticket=100 ;/** *不同线程使用同一个锁对象 */ private Object obj = new Object(); @Override public void run() { while(true) { /** * 使用synchornized(obj) {} 代码块 */ synchronized (obj) { if (ticket > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "sale=====" + ticket); ticket--; } } } } } public class SaleTicketDemoTest { public static void main(String[] args) { SaleTicket sale = new SaleTicket(); //开启3个线程操作同一对象,从而操作同一资源 Thread th1 = new Thread(sale); Thread th2 = new Thread(sale); Thread th3 = new Thread(sale); th1.start(); th2.start(); th3.start(); } }
同步方法
public synchornied void 方法名(){
//涉及操作同一资源的方法
}
同步方法的锁:
同步方法的锁使用的是this对象,即new Thread(Xxx) 的Xxx对象
package com.test.java;/** *模拟买票功能,开启多个线程,同时买一百张票 */ public class SaleTicket implements Runnable{ /* 不同对象使用同一个变量 */ private static int ticket=100 ; /** *不同线程使用同一个锁对象 */ private Object obj = new Object(); @Override public void run() { while(true) { saleTicket(); } } /** * 定义个个同步方法 public snychonized void XXX(){} */ public synchronized void saleTicket() { if (ticket > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "sale=====" + ticket); ticket--; } } }
静态的同步方法
public static sychornized xxx(){
//涉及操作共同资源的代码
}
静态同步方法的锁是类名.class对象
package com.test.java;/** *模拟买票功能,开启多个线程,同时买一百张票 */ public class SaleTicket implements Runnable{ /* 不同对象使用同一个变量 */ private static int ticket=100 ; /** *不同线程使用同一个锁对象 */ private Object obj = new Object(); @Override public void run() { while(true) { saleTicket(); } /** * 静态同步方法 */ public static synchronized void saleTicket() { if (ticket > 0) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "sale=====" + ticket); ticket--; } } }
锁机制
lock的好处:解决了当共享资源的锁一直未被释放,其他线程无限等待的问题。
Jdk1.5后在java.util.concurrent.locks
当多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操 作。因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到
Lock和synchornized的区别:- Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这 个类可以实现同步访问;
- Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。
- 采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。通常使用Lock来进行同步的话
- Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这 个类可以实现同步访问;
线程池
以上是关于线程同步&线程池的主要内容,如果未能解决你的问题,请参考以下文章