首页 > 代码库 > 多线程-6

多线程-6

六、线程安全 synchronized

1.诸如多窗口售票、查询对象是否存在的情况会出现线程安全的问题,引发线程安全有如下几个条件:
a.肯定要是多线程环境
b.有共同操作到的数据
c.线程间会受到彼此操作数据的影响。

2.java通过同步机制synchronize关键字来处理线程安全的问题。同步可以同步代码,也可以同步方法。同步方法的锁是this关键字,所以同步方法和使用this关键字的同步代码一起使用也可以达到同步的效果。
a.同步代码
synchronized(对象){
需要同步的代码;
}
b.同步方法
public synchronized void sail(){
方法体;
}

3.关于该使用什么样的锁的思考。首先,锁肯定不能用对象,因为对象在静态后面加载,使用字节码对象比对象更好。然后是this和字节码对象的对比。使用this的时候,只要是同一个对象的都是线程安全的;使用字节码的是所有的使用者都线程安全。有如StringBuffer的方法使用比较多,每个使用的对象自身线程安全,而不必保证所有的使用对象线程安全。

4.关于集合的线程安全。很多集合出于性能的考虑是线程不安全的,要想使用线程安全的集合,Collections工具类提供了相应的方法,入:
List<String> list = Collections
.synchronizedList(new ArrayList<String>());

示例代码:
1.继承的方式实现线程安全的卖票:
public class SailTicket extends Thread {
//继承方式共享数据要使用static
static int ticketNum = 100;

@Override
public void run() {

while(true){
synchronized (SailTicket.class) {

if (ticketNum > 0) {
try {
//未模拟网络延迟的情况
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

System.out.println(getName() + "窗口正在出售" + ticketNum-- + "张票!");
}else{
break;
}
}
}
}
}

public class SailTicketTest {
public static void main(String[] args) {
SailTicket st = new SailTicket();
SailTicket st2 = new SailTicket();
SailTicket st3 = new SailTicket();

st.setName("一号");
st2.setName("二号");
st3.setName("三号");

st.start();
st2.start();
st3.start();
}
}

2.实现类的方式实现线程安全的卖票:
public class SailTicketForImpl implements Runnable {
int i = 1;
int ticketNum = 100;

@Override
public void run() {
while(true){
if(i % 2 ==0){
synchronized(this){
if(ticketNum > 0){
System.out.println(Thread.currentThread().getName() + "窗口正在出售" + ticketNum-- + "张票!");
}
}
}else if(i % 2 != 0 ){
sail();
}
if(ticketNum <= 0){
break;
}
}
}

public synchronized void sail(){
if(ticketNum > 0 ){
System.out.println(Thread.currentThread().getName() + "窗口正在出售" + ticketNum-- + "张票!");
}
}

}

public class SailTicketForImplTest {
public static void main(String[] args) {
SailTicketForImpl sailTicket = new SailTicketForImpl();

Thread st1 = new Thread(sailTicket , "一号");
Thread st2 = new Thread(sailTicket , "二号");
Thread st3 = new Thread(sailTicket , "三号");

st1.start();
st2.start();
st3.start();
}
}

3.获得线程安全的集合:
public class ThreadDemo {
public static void main(String[] args) {

// public static <T> List<T> synchronizedList(List<T> list)
List<String> list1 = new ArrayList<String>();// 线程不安全
List<String> list2 = Collections
.synchronizedList(new ArrayList<String>()); // 线程安全
}
}

多线程-6