public class SellTicket implements Runnable{
private int tickets=10;
@Override
public void run(){
while (true){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张票");
tickets--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
public class SellTicketDemo {
public static void main(String[] args) {
SellTicket st= new SellTicket();
Thread t1=new Thread(st,"李昊");
Thread t2=new Thread(st,"朱长坤");
Thread t3=new Thread(st,"杨天伦");
t1.start();
t2.start();
t3.start();
}
}
相同的票出现了多次
出现了负数票
原因是线程执行的随机性导致的
锁多条语句操作共享数据,可以使用同步代码块实现
格式
syschronized(任意对象){
多条语句操作共享数据的代码
}
public class SellTicket implements Runnable{
private int tickets=10;
private Object obj=new Object();
@Override
public void run(){
while (true){
synchronized(obj){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张票");
tickets--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
}
同步的好处和弊端
格式
修饰符 synchronized 返回值类型 方法名(方法参数){
}
public class SellTicket implements Runnable{
private int tickets=10;
private int x=0;
@Override
public void run(){
while (true){
if(x%2==0){
synchronized(this){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
tickets--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
else{
sellTicket();
}
x++;
}
}
private synchronized void sellTicket(){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
tickets--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
同步方法的锁对象是this
public class SellTicket implements Runnable{
private static int tickets=10;
private int x=0;
@Override
public void run(){
while (true){
if(x%2==0){
synchronized(SellTicket.class){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
tickets--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
else{
sellTicket();
}
x++;
}
}
private static synchronized void sellTicket(){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+":正在卖第"+tickets+"张AV");
tickets--;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
从Java 2平台v1.2开始,该类改进了List接口,使其成为JavaCollections Framework的成员。与新的集合实现不同,Vector被同步。如果不需要线程安全的实现,建议使用ArrayList代替Vector
**Collections.synchronizedList()**可返回线程安全的ArrayList
同理map也可以Collections.synchronizedMap()
为了更清晰地表达如何加锁和释放锁,JDK5后提供了一个新的锁对象Lock
Lock提供了比使用synchronized方法和语句更为广泛的锁定操作
Lock中获得锁和释放锁的方法:
Lock接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
构造方法:ReentrantLock():创建一个ReentrantLock的实例
public class SellTicket implements Runnable{
private int tickets=20;
private Lock lock=new ReentrantLock();
@Override
public void run(){
while (true){
try{
lock.lock();
if (tickets>0){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(Thread.currentThread().getName()+"正在卖第"+tickets+"张av");
tickets--;
}
}finally {
lock.unlock();
}
}
}
}