java中什么是线程不安全给出一个例子
下面我们再给出一个线程不安全的例子。
马克- to-win:马克 java社区:防盗版实名手机尾号: 73203。
例:1.8.2-本章源码
class BookMark_to_win {
int bookNum=10;
void onlySellOne() {
if (bookNum > 0) {
System.out.println(Thread.currentThread().getName()
+ " before" + bookNum);
bookNum--;
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName()
+ " after " + bookNum);
}
}
}
public class Test {
public static void main(String[] args) {
BookMark_to_win bookM = new BookMark_to_win();
while (bookM.bookNum>0) {
bookM.onlySellOne();
}
}
}
输出结果:
main before10
main after 9
main before9
main after 8
main before8
main after 7
main before7
main after 6
main before6
main after 5
main before5
main after 4
main before4
main after 3
main before3
main after 2
main before2
main after 1
main before1
main after 0
后续:在以上的例子中,我们编了一个方法叫onlySellOne。这个方法的目的就是每一次只卖一本书。单线程的环境下,我们看到结果符合我们的预期。下面我们就把它放在一个多线程的环境下测试。
马克-to-win:下面的例子是比较明显的,本来说好了,if (bookNum > 0)的话,我才买书,因为没有书,卖什么?而现在却把书卖出了负数,这已经明显不符合逻辑了。要是银行账号的话,你的账号就能成为负值,意味着你花了银行的钱。只要方法中有关键变量又有判断还要改变此变量,线程安全的错误就会比较邪乎!(比如单态中也有判断)没判断,虽然也错,不那么邪乎!
例:1.8.2_b-本章源码
class BookMark_to_win {
int bookNum=1;
void onlySellOne() {
if (bookNum > 0) {
System.out.println(Thread.currentThread().getName()
+ " before" + bookNum);
bookNum--;
try {
Thread.sleep(1000);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName()
+ " after " + bookNum);
}
}
}
class MyThread extends Thread {
BookMark_to_win book;
MyThread(BookMark_to_win tmp) {
this.book = tmp;
}
public void run() {
while (book.bookNum>0) {
book.onlySellOne();
}
}
}
public class Test {
public static void main(String[] args) {
BookMark_to_win bookM = new BookMark_to_win();
Thread t1 = new MyThread(bookM);
Thread t2 = new MyThread(bookM);
t1.start();
t2.start();
}
}
输出结果:
Thread-0 before1
Thread-1 before1
Thread-1 after -1
Thread-0 after -1
后续:我们仔细观察会发现:Thread-0 before1 Thread-0 after -1,线程0之前读出有1本书,调用了onlySellOne后,里面只做了一次"bookNum--"操作,发现结果是“Thread-0 after -1”即为还剩-1本书。为什么1-1=-1呢?原来线程0调用onlySellOne的"bookNum--";时,线程1正好也执行到这,调用了"bookNum--"; 所以实际上是1-1-1=-1;既然我们预期"bookNum--"是每次只卖一本书,单线程环境执行挺好,而在多线程环境下,得到了一次减两本的结果,典型属于线程不安全。