并发是指一个对象多个线程同时操作 ,这样就会有问题,
一般会出现两种问题,
一种就是 某一块数据同时操作重复多次; 这个是由于各个线程有不同的线程都有不同的操作空间来和主存交互,如果a和主存拷贝数据,修改后没有提交到主存之前,b也拷贝了这个数据,那这个时候就会出现 这种情况;
另外就是会出现操作超了临界点的情况,到临界点的时候由于网络延迟,线程操作数据被延时,实际上早就应该停止,因为延迟,就会出现超出了临界点的操作;
&&&&&&&&&&&&&&&&&&&
线程同步
这就是并发,处理这种情况就是加锁控制,一个对象的等待池形成队列,a进程开始操作,就对这块数据 锁起来,直到a完成,再解除锁定,b再操作,
加锁的话会造成性能的损耗,但是线程安全会比较重要, 如何在性能和线程安全中取得一个平衡点,这是代码优化的重点,所谓的高性能
加锁的情况只是针对于有写操作的,如果只读没必要加锁;
*****************************
每个对象都有一个锁 synchronized 锁对象锁资源,
一般可以 锁 某一个具体的对象/this成员(成员方法)/对象的模子class(静态方法)
锁可以分为 同步方法 和同步块;
同步块的优化是难点,如何锁对又准确 那么将是一个吃功底的操作;
具体例子1 模拟抢票
优化前
package y.i.d;
// 多个代理线程共享个一份资源这个时候就会存在并发问题,这个时候我们就要保证线程安全(数据准确);
public class Web12306 implements Runnable {
int titcke=100;
public static void main(String[] args){
Web12306 web12306 =new Web12306();
new Thread(web12306,"111").start();
new Thread(web12306,"222").start();
new Thread(web12306,"333").start();
}
@Override
public void run() {
// TODO Auto-generated method stub
while (true) {
if(titcke<=0) {
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"->>"+titcke--);
}
}
}
优化后
package y.i.d;
// 多个代理线程共享个一份资源这个时候就会存在并发问题,这个时候我们就要保证线程安全(数据准确);
public class Web12306 implements Runnable {
int titcke=100;
boolean flag=true;
public static void main(String[] args){
Web12306 web12306 =new Web12306();
new Thread(web12306,"111").start();
new Thread(web12306,"222").start();
new Thread(web12306,"333").start();
}
@Override
public void run() {
// TODO Auto-generated method stub
while (flag) {
test();
}
}
public synchronized void test() { // 加锁 锁的是this
if(titcke<=0) {
flag=false;
return;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"->>"+titcke--);
}
}
例子2
优化前
package y.i.d;
public class Drawing {
public static void main(String[] args){
Account a1=new Account(100, "总账号");
Drawior you1= new Drawior(a1, 40, "悲哀的你");
Drawior wife= new Drawior(a1, 70, "快乐的她");
you1.start();
wife.start();
}
}
class Account {
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
class Drawior extends Thread{
Account account;
int drawMoney;
int packageMoney;
@Override
public void run() {
if(drawMoney>account.money) {
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
account.money-=drawMoney;
packageMoney+=drawMoney;
System.out.println(this.getName()+"-->账户的钱-->"+account.money);
System.out.println(this.getName()+"-->口袋的钱-->"+packageMoney);
}
public Drawior(Account account, int drawMoney, String name) {
super(name);
this.account = account;
this.drawMoney = drawMoney;
}
}
优化后
package y.i.d;
public class Drawing {
public static void main(String[] args){
Account a1=new Account(100, "总账号");
Drawior you1= new Drawior(a1, 40, "悲哀的你");
Drawior wife= new Drawior(a1, 70, "快乐的她");
you1.start();
wife.start();
}
}
class Account {
int money;
String name;
public Account(int money, String name) {
this.money = money;
this.name = name;
}
}
class Drawior extends Thread{
Account account;
int drawMoney;
int packageMoney;
public void test() {
if(drawMoney>account.money) { // 第一次判断 性能优化 直接少加锁 ,这里是减少了加锁次数,提升了性能,但是没有保证线程安全
return;
}
synchronized(account) { // 这里使用同步块控制, 括号的参数对象称之为 同步控制器 锁谁直接告诉我,也可以直接传this 。同步方法 锁的是this
if(drawMoney>account.money) { // 第二次判断 保证线程安全临界点的问题 这叫做双重检测 double checking
return;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
account.money-=drawMoney;
packageMoney+=drawMoney;
System.out.println(this.getName()+"-->账户的钱-->"+account.money);
System.out.println(this.getName()+"-->口袋的钱-->"+packageMoney);
}
}
public void run() {
test();
}
public Drawior(Account account, int drawMoney, String name) {
super(name);
this.account = account;
this.drawMoney = drawMoney;
}
}
demo1 快乐影院 多线程操作 同步块
package y.i.d;
import java.util.ArrayList;
import java.util.List;
public class HappyCinema {
public static void main(String[] args){
List<Integer> available = new ArrayList<Integer>();
available.add(1);
available.add(8);
available.add(3);
available.add(2);
available.add(5);
List<Integer> customer = new ArrayList<Integer>();
customer.add(1);
customer.add(8);
customer.add(3);
List<Integer> customer1 = new ArrayList<Integer>();
customer1.add(1);
customer1.add(5);
customer1.add(2);
Cinema cinema= new Cinema(available, "happyCinema");
new Thread(new Customer(cinema,customer),"xiaoming").start();
new Thread(new Customer(cinema,customer1),"long").start();
}
}
class Customer implements Runnable {
Cinema cinema;
List<Integer> seats;
public Customer(Cinema cinema,List<Integer> seats) {
this.cinema = cinema;
this.seats= seats ;
}
public void run() {
synchronized (cinema) { //同步块控制,同步资源
boolean flag = cinema.bookTickets(seats);
if(flag) {
System.out.println("购票成功,购票人为"+Thread.currentThread().getName()+"位置为"+seats+"可用位置为" + cinema.available );
}else {
System.out.println("购票失败,购票人为"+Thread.currentThread().getName()+"位置为"+seats+"可用位置为" + cinema.available);
}
}
}
}
class Cinema{
List<Integer> available; // 可用的位置
String name; // 名字
public Cinema(List<Integer> available,String name) {
this.name=name;
this.available=available;
}
public boolean bookTickets(List<Integer> seats) {
System.out.println("可用的位置为"+available);
List<Integer> copy = new ArrayList<Integer>();
copy.addAll(available);
copy.removeAll(seats);
if(available.size()-copy.size()!=seats.size()) {
return false;
}
available = copy;
return true;
}
}
demo2 同步方法 锁定this
package y.i.d;
import java.util.ArrayList;
import java.util.List;
public class HappyCinema {
public static void main(String[] args){
List<Integer> available = new ArrayList<Integer>();
available.add(1);
available.add(8);
available.add(3);
available.add(2);
available.add(5);
List<Integer> customer = new ArrayList<Integer>();
customer.add(1);
customer.add(8);
customer.add(3);
List<Integer> customer1 = new ArrayList<Integer>();
customer1.add(1);
customer1.add(5);
customer1.add(2);
Cinema cinema= new Cinema(available, "happyCinema");
new Thread(new Customer(cinema,customer),"xiaoming").start();
new Thread(new Customer(cinema,customer1),"long").start();
}
}
class Customer implements Runnable {
Cinema cinema;
List<Integer> seats;
public Customer(Cinema cinema,List<Integer> seats) {
this.cinema = cinema;
this.seats= seats ;
}
public void run() {
cinema.test(seats);
}
}
class Cinema{
List<Integer> available; // 可用的位置
String name; // 名字
public Cinema(List<Integer> available,String name) {
this.name=name;
this.available=available;
}
public boolean bookTickets(List<Integer> seats) {
System.out.println("可用的位置为"+available);
List<Integer> copy = new ArrayList<Integer>();
copy.addAll(available);
copy.removeAll(seats);
if(available.size()-copy.size()!=seats.size()) {
return false;
}
available = copy;
return true;
}
public synchronized void test(List<Integer> seats) {
boolean flag = this.bookTickets(seats);
if(flag) {
System.out.println("购票成功,购票人为"+Thread.currentThread().getName()+"位置为"+seats+"可用位置为" + this.available );
}else {
System.out.println("购票失败,购票人为"+Thread.currentThread().getName()+"位置为"+seats+"可用位置为" + this.available);
}
}
}