
同步问题2、父子线程间打开同一个文件不仅仅只是共享一个inode的问题,它们甚至还共享同一个files数据结构,也就是说文件偏移量都是共享的,那如果线程a在调用write方法的时候,如果被线程b中断又会出现什么样的问题。1 定义: 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,形成线程的死锁。上面程序使用@synchronized将draw:方法的方法体修改成同步代码块,该同步代码块的同步监视器是lcaccount对象本声,这样做法符合”加锁→修改→释放锁”的逻辑,任何线程在修改制定资源之前,首先都要对该资源加锁,在加锁期间其他线程无法修改该资源,当该线程修改完成后,释放对该资源的锁定.通过这种方式就可以保证并发线程在任一时刻只有一个线程可以进入修改共享资源的代码区(也称为临界区),所以同一时刻最多只有一个线程处于临界区内,从而保证了线程的安全性.。
举个例子:比如我卖100张票,通过三个窗口卖,那么可以用如下代码实现。
public class MultipleThread {
public static void main(String[] args) {
SingleThread st = new SingleThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
Thread t3 = new Thread(st);
t1.start();
t2.start();
t3.start();
}
}
class SingleThread implements Runnable {
private int totalTicket = 100;
@Override
public void run() {
while (true) {
if (totalTicket > 0)
try {
Thread.sleep(10);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + " sell ticket " + totalTicket--);
}
}
}
}
/*
Thread-0 sell ticket 1
Thread-2 sell ticket 0
Thread-1 sell ticket -1*/
这个程序可以通过三个窗口卖完100个票,但是可能出现问题是,比如我们卖到只剩一张票时,一个窗口卖了这张的时候,还没卖完,另一个窗口查系统的时候看到还剩一张,就也卖这张票,这时就可能出现一张票被多次售卖了。因为有共享数据,这就多线程出现了安全问题。
多线程安全问题原因:当多条线程同时操作一个共享数据时,一个线程还没执行完,另一个线程就也进来执行共享数据,就可能会出现共享数据错误。
它允许应用程序在执行一个可能不安全或敏感的操作前确定该操作是什么,以及是否是在允许执行该操作的安全上下文中执行它。比如当线程a对x自加运算的时候java多线程死锁,编译后的自加运算共分为三步,当没有执行完这三步的时候,可能线程a就会被切出(比如说有需要即时响应的操作发生)。当使用synchronized 来修饰某个共享资源时(分同步代码块和同步方法两种情况),当某个线程获得共享资源的锁后就可以执行相应的代码段,直到该线程运行完该代码段后才释放对该共享资源的锁,让其他线程有机会执行对该共享资源的修改。
synchronized(对象)
{
需要同步的代码(操作共享数据的代码)
}
public class MultipleThread {
public static void main(String[] args) {
SingleThread st = new SingleThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
Thread t3 = new Thread(st);
t1.start();
t2.start();
t3.start();
}
}
class SingleThread implements Runnable {
//共享变量
private int totalTicket = 100;
//共享对象
private Object o = new Object();
@Override
public void run() {
while (true) {
synchronized (o) {//同步必须是同一个对象
if (totalTicket > 0) {
try {
Thread.sleep(10);
} catch (Exception e) {
}
System.out.println(Thread.currentThread().getName() + " sell ticket " + totalTicket--);
}
}
}
}
}
同步的好处:解决了多线程安全问题。
弊端:每次都需要判断锁,会消耗资源

),这个家庭要存18 次,假设每次存x 元,第一次存的x 元需要存期为18 年,第二次存的x 元实际上在银行存了17 三次16年,依次类推…………到第18 次存期为1 年,那么数学论文一个小 数点与一场大悲剧 1967 23日,前苏联著名宇航员费拉迪米尔。也就是像把钱存进银行一样获得利息,但把钱存到余额宝里而不是银行里面,在存钱额度相同的情况下在余额宝获得的收益比银行多得多。8、对账的内容包括账证核对(账簿与会计凭证)、账账核对(总账与总账、总账与日记账、总账与明细账、明细账之间核对)、账实核对(日记账与库存、银行日记账与银行对账单、财产物资明细账与财产物资的实有数额、债权债务明细账与对方单位的账面记录)。
实现代码:
public class MultipleThread {
public static void main(String[] args) {
Customer customer = new Customer();
Thread t1 = new Thread(customer);
Thread t2 = new Thread(customer);
Thread t3 = new Thread(customer);
t1.start();//客户1跑线程1
t2.start();
t3.start();
}
}
//银行总账类
class Bank {
private int moneySum = 0;
void addMoney(int n) {
moneySum = moneySum + n;
try {
Thread.sleep(10);
} catch (Exception e) {
}
System.out.println("sum = " + moneySum);
}
}
//用户类:因为要创建多个用户执行多线程,所以该类实现Runnable
class Customer implements Runnable {
//此对象为多线程共享对象
private Bank bank = new Bank();
//存钱,存三次
@Override
public void run() {
for (int i = 0; i < 3; i++) {
System.out.println(Thread.currentThread().getName() + " save money:");
bank.addMoney(100);
}
}
}
/*
Thread-0 save money:
Thread-1 save money:
Thread-2 save money:
sum = 300
Thread-0 save money:
sum = 300
Thread-1 save money:
sum = 500
Thread-2 save money:
sum = 600
Thread-1 save money:
sum = 700
Thread-0 save money:
sum = 800
Thread-2 save money:
sum = 900
sum = 900
sum = 900
*/
这时我们发现,操作共享数据出现问题,打印出了错误的银行总账。这是因为我们操作共享数据时没有进行同步,也就是说多个线程同时操作一个共享变量。
解决:
**先明确共享数据,然后明确多线程代码中哪些语句是操作共享数据的。**如果弄错了同步的语句块,可能会造成多线程编程串行程序而顺序执行就不是并发了。
我们发现
private Bank bank = new Bank();
private int moneySum = 0;
是共享数据

操作共享数据的语句为:
bank.addMoney(100);以及他内部语句
然后我们可以通过同步代码块和同步函数来进行解决。
同步代码块中的对象是唯一的,他称为一个同步锁(互斥锁),当一个线程持有该锁,其他线程不能够使用该锁。也就是通过这个唯一锁每次持有该锁的线程才能执行代码。一个线程执行完之后释放该锁,其他线程来拿到锁继续执行。
synchronized(对象)
{
需要同步的代码(操作共享数据的代码)
}
public class MultipleThread {
public static void main(String[] args) {
Customer customer = new Customer();
Thread t1 = new Thread(customer);
Thread t2 = new Thread(customer);
Thread t3 = new Thread(customer);
t1.start();//客户1跑线程1
t2.start();
t3.start();
}
}
//银行总账类
class Bank {
private int moneySum = 0;
void addMoney(int n) {
moneySum = moneySum + n;
try {
Thread.sleep(10);
} catch (Exception e) {
}
System.out.println("sum = " + moneySum);
}
}
//用户类:因为要创建多个用户执行多线程,所以该类实现Runnable
class Customer implements Runnable {
//此对象为多线程共享对象
private Bank bank = new Bank();
Object O = new Object();
//存钱,存三次
@Override
public void run() {
for (int i = 0; i < 3; i++) {
synchronized (O) {
System.out.println(Thread.currentThread().getName() + " save money:");
bank.addMoney(100);
}
}
}
}
/*
Thread-0 save money:
sum = 100
Thread-0 save money:
sum = 200
Thread-0 save money:
sum = 300
Thread-2 save money:
sum = 400
Thread-2 save money:
sum = 500
Thread-2 save money:
sum = 600
Thread-1 save money:
sum = 700
Thread-1 save money:
sum = 800
Thread-1 save money:
sum = 900
*/
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-107572-1.html
最先进的濒海战斗舰不就驻扎在新加坡么~