多线程共享资源涉及到的线程安全问题:这里列出 Synchronized 和 Lock两种方式。
Synchronized方式:
public class Synchronized {
public static void main(String[] args) {
Thread sthread= new Thread();
new Thread(new User("张","12")).start();
new Thread(new User("王","13")).start();
new Thread(new User("李","14")).start();
new Thread(new User("宋","15")).start();
}
}
class User implements Runnable{
private String selectedSeat;
private String name;
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(String name,String selectedSeat) {
super();
this.selectedSeat = selectedSeat;
this.name = name;
}
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (User.class) {
System.out.println("进入选座");
System.out.println("选!");
System.out.println("选座完成");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
通过锁住类实现锁机制,多个线程执行run方法按顺序输出。 通过在方法上加锁不成功。
Lock方式:
public class LockDemo {
public static void main(String[] args) {
product p = new product();
Lock l =new ReentrantLock(true);
new Thread(new Producer(p,l)).start();
new Thread(new Consumer(p,l)).start();
}
}
class product{
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
class Producer implements Runnable{
private product p;
private Lock l;
public Producer(product p, Lock l) {
super();
this.p = p;
this.l = l;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
l.lock();
int count = (int)(p.getCount()+1000*Math.random());//现有+生产
p.setCount(count); //总共
System.out.println("产品总数"+p.getCount());
l.unlock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable{
private product p;
private Lock l;
public Consumer(product p, Lock l) {
super();
this.p = p;
this.l = l;
}
@Override
public void run() {
while(true){
l.lock();
// TODO Auto-generated method stub
int count = (int)(p.getCount()*Math.random());//消费数
System.out.println("消费----"+count);
p.setCount(p.getCount()-count); //产品剩余
System.out.println("消费完剩余"+p.getCount());
l.unlock();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
这也就是生产者-消费者问题。
Lock中的公平策略: 线程执行完后等待其他抢夺 ReentrantLock(false);
非公平策略 :线程执行完后依然可以参与 ReentrantLock(true);
比较与总结:
lock 比 synchronized更加灵活 ,synchronized会造成线程被阻塞又没有释放锁,这在实际应用中会严重影响程序执行效率。
synchronized不需要手动释放锁,lock必须手动释放锁。
synchronized中实现Runnable接口比继承Thread方便代码拓展