zoukankan      html  css  js  c++  java
  • java && C# 线程

     

    1、多个线程用到同一个资源的话,必须lock

    2、为了解决,在竞争的情况下,优先分配资源给A。就是A和B线程都同时在同一时刻需要资源x,然后的话也不清楚系统是具体怎样调度的。或者说怎样调度,都有可能出现上面的问题。解决方法是:在分配资源的时候再增加一个请求,用来排队。以前的请求是,如果这个时候申请然后这个时候也没人在用,就给它。现在的是如果B需要x,先要查看A是否需要。感觉有点像增加代码,然后使得线程判断次数增加,多次调度。所以感觉没有根本解决问题。

    也不是说没解决,但是感觉解决了99.9%。hack,对于同一时刻到来的,还是随机化先进性读,或者先进性写了。T__T

    怎么说呢,就是读者一来,先申请需要资源,而不是判定是否能拿资源,然后能拿就给它。我们需要的是先申请,然后就相当于锁定了资源x了,后来的写者再需要,需要检查申请队列中是否有读者,有就不行。

    3、合法后立马addSignal,不然会出现多个写者同时操作的问题。

    4、get, set方法是有用的,对于多线程,还可以维护资源不被多个线程修改,Lock

     

    所以我的感觉是:如果是这样的:

    写者先判定while (getNeedReader() > 0) { },判断失败的。

    然后读者addReader(1); 

    然后写者while (getSignal() != 0) { } 也是失败的。

    这样的话,结果还是给了写者。

    很多人告诉我直接设置线程优先级,但是这样是不对的。因为线程的优先级只是说分配的时间片比较多,不保证上面的情况不能发生。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    namespace WindowsFormsApp1 {
        public partial class Form1 : Form {
            static int signal = 0;//0:empty 1:read 2:write
            static int numberReader = 0, numberWriter = 0;
            private static object obj = new object();
            private static object si = new object();
            private static object reader = new object();
            const int dis = 1000;
            static Stopwatch timer1;
            static int needReader = 0;
            class temp {
                public string[] str;
                int getSignal() {
                    lock (si) {
                        return signal;
                    }
                }
                int getNumber() {
                    if (0 == getSignal()) return 0;
                    else if (1 == getSignal()) return numberReader;
                    else return numberWriter;
                }
                void addSignal(int id) {
                    lock (si) {
                        if (id == 1) {
                            signal = 1;
                            numberReader++;
                        } else {
                            signal = 2;
                            numberWriter++;
                        }
                    }
                }
                void cutSignal(int id) {
                    lock (si) {
                        if (id == 1) {
                            numberReader--;
                            if (numberReader == 0) signal = 0;
                        } else {
                            numberWriter--;
                            if (numberWriter == 0) signal = 0;
                        }
                    }
                }
    
    
    
                void addStringRichText(String str) {
                    lock (obj) {
                        Form1.richTextBox1.Text += str;
                        Form1.richTextBox1.Text += '
    ';
                        Form1.richTextBox1.Focus();
                        Form1.richTextBox1.Select(Form1.richTextBox1.Text.Length, 0);
                        Form1.richTextBox1.ScrollToCaret();
    
                    }
                }
    
                void show(String[] str, int id) {
                    Console.Write(id + "+++ ");
                    for (int i = 0; i < str.Length; ++i) {
                        Console.Write(str[i] + " ");
                    }
                    Console.WriteLine("
    ");
                }
    
                void addReader(int op) {
                    lock (reader) {
                        needReader += op;
                    }
                }
    
                int getNeedReader() {
                    lock (reader) {
                        return needReader;
                    }
                }
    
                void semWait(int id) {
                    if (id == 1) {
                        addReader(1); // 首先需要申请需要资源,直接资源锁定
                        if (getSignal() != 2) {
                            addSignal(id);
                            return;
                        }
                        while (getSignal() == 2) { } // 合法后立马addSignal
                        addSignal(1);
                    } else {                    
                        while (getNeedReader() > 0) { }
                        while (getSignal() != 0) { } //这句后面肯定要是addSignal,立马的
                        addSignal(2);
                    }
                }
    
                void semSignal(int id) {
                    if (id == 1) {
                        cutSignal(1);
                        addReader(-1);
                    } else {
                        cutSignal(2);
                    }
                }
    
                public void Reader() {
                    addStringRichText("读者:" + str[0] + " 线程创建");
                    Thread.Sleep(int.Parse(str[2]) * 1000);
                    addStringRichText("读者:" + str[0] + " 在时间:" + (int)timer1.Elapsed.TotalSeconds + " 请求读操作");
    
                    /*进行读操作*/
                    semWait(1);
                    addStringRichText("读者:" + str[0] + " 在时间:" + (int)timer1.Elapsed.TotalSeconds + " 开始读操作");
                    Thread.Sleep(int.Parse(str[3]) * 1000);
                    addStringRichText("读者:" + str[0] + " 在时间:" + (int)timer1.Elapsed.TotalSeconds + " 结束读操作");
                    semSignal(1);
                    /*读操作进行完毕*/
    
    
    
                }
                private static object w = new object();
                public void Writer() {
                    addStringRichText("写者:" + str[0] + " 线程创建");
                    Thread.Sleep(int.Parse(str[2]) * 1000);
                    addStringRichText("写者:" + str[0] + " 在时间:" + (int)timer1.Elapsed.TotalSeconds + " 请求写操作");
    
                    semWait(2);
                    /*进行读操作*/
    
                    addStringRichText("写者:" + str[0] + " 在时间:" + (int)timer1.Elapsed.TotalSeconds + " 开始写操作");
                    Thread.Sleep(int.Parse(str[3]) * 1000);
                    addStringRichText("写者:" + str[0] + " 在时间:" + (int)timer1.Elapsed.TotalSeconds + " 结束写操作");
                    semSignal(2);
                    /*读操作进行完毕*/
    
                }
    
            }
            public Form1() {
                InitializeComponent();
            }
            private void button1_Click(object sender, EventArgs e) {
                OpenFileDialog op = new OpenFileDialog();
                op.ShowDialog();
                op.Filter = "All files(*.*)|*.*";
                StreamReader reader = null;
    
                try {
                    string fileName = op.FileName;
                    if (fileName == "") {
                        return;
                    }
                    richTextBox1.Clear();
                    reader = new StreamReader(fileName, System.Text.Encoding.Default);
                    string str = reader.ReadLine();
                    List<Thread> list = new List<Thread>();
                    while (str != null) {
                        string[] res = str.Split(' ');
                        temp zhu = new temp();
                        zhu.str = res;
                        if (str.Contains("R") || str.Contains("r")) {
                            Thread rThread = new Thread(zhu.Reader);
                            //rThread.Priority = ThreadPriority.AboveNormal;
                            rThread.Priority = ThreadPriority.AboveNormal;
                            list.Add(rThread);
    
                        } else if (str.Contains("W") || str.Contains("w")) {
                            Thread wThread = new Thread(zhu.Writer);
                            //wThread.Priority = ThreadPriority.BelowNormal;
                            list.Add(wThread);
                        } else {
                            MessageBox.Show("输入数据有错误!!!【每行数据后面不能有空格】,【文件结束不能有空行】");
                            return;
                        }
                        //MessageBox.Show(str);
                        str = reader.ReadLine();
                    }
                    timer1 = new Stopwatch();//计时器类
                    timer1.Start();
                    foreach (Thread i in list) {
                        i.Start();
                    }
                } catch (Exception error) {
                    MessageBox.Show("错误信息是:" + error.Message, "警告", MessageBoxButtons.OK, MessageBoxIcon.Error);
    
                } finally {
                    if (reader != null) {
                        reader.Close();
                    }
                }
                const string MutexName = "Multithreading";
                var m = new Mutex(false, MutexName);
    
    
            }
            private void richTextBox1_TextChanged(object sender, EventArgs e) {
            }
            private void Form1_Load(object sender, EventArgs e) {
                System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false; //允许其他线程修改
            }
        }
    }
    View Code

    所以,我感觉线程不是用于这样的东西的,这样的话结果不确定(或者是我太渣渣了)

    线程应该是用在那些,计算方面,new一个线程来辅助计算

    这个数据,就会显示是写者优先了,尽管我设置了优先级是读者AboveNormal

    对了看到java里写,Main线程的优先级是Noraml的。

    2 W 1 5
    2 W 1 5
    2 W 1 5
    2 W 1 5
    2 W 1 5
    2 W 1 5
    2 W 1 5
    1 R 1 5
    View Code

    java说,

    synchronized可以修饰一个同步一个方法,public synchronized void fun();

    同步:就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。

    java高级篇P326

    一个同步方法在执行之前需要加锁,锁是一种实现资源排他使用的机制。对于实例方法,要给调用该方法的对象加锁。对于静态方法,要给这个类加锁。

     但是我不需要对整个类加锁啊,我对静态方法加锁也可以得,???不懂

    class myThread implements Runnable {
        public String s;
    
        public void run() {
            System.out.println(s);
        }
    
        static synchronized void fun() {
            
        }
    }

    java的内部类如果需要new一个实体出来,

    用name s = new name(); 是不行的。会"is not an enclosing class"

    需要Main s = new Main(); 一个实例

    然后Main.name bb = s.new name();

    有一个问题就是,用lock的话,怎么解决只有一个return的语句呢???

    因为lock.lock()之后,还需要lock.unlock()

    import java.text.SimpleDateFormat;
    import java.util.*;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    public class Main {
        static bank bk = new bank();
        public static void main(String[] args) {
            ExecutorService ex = Executors.newCachedThreadPool();
            ex.execute(new cutMoney());
            ex.execute(new addMoney());
            ex.shutdown();
        }
        static class addMoney implements Runnable {
            @Override
            public void run() {
                while (true) {
                    int val = (int)(Math.random() * 10) + 1;
                    bk.add(val);
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        static class cutMoney implements Runnable {
            @Override
            public void run() {
                while (true) {
                    int val = (int)(Math.random() * 10) + 1;
                    try {
                        while (!bk.cut(val)) {}
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
        
        static class bank {
            private Lock lock = new ReentrantLock();
            private Condition signal = lock.newCondition();
            private int money = 0;
            bank() {}
    //        synchronized int getMoney() { // 只能这样嘛?用lock感觉不行啊
    //            return money;
    //        }
            int getMoney() { // 只能这样嘛?用lock感觉不行啊
                lock.lock();
                try {
                    return money;
                } finally {
                    lock.unlock();
                }
            }
            String getNowTime() {
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");//设置日期格式
                return (df.format(new Date()));// new Date()为获取当前系统时间
            }
            boolean cut(int val) throws InterruptedException {
                lock.lock();
                try {
                    while (money < val) {
                        System.out.println(getNowTime() + " 不够  " + val + "  " + "   现在有 " + money);
                        signal.await(); //等待,不需要一直判判判
                    }
                    money -= val;
                    System.out.println(getNowTime() + " 扣除" + val + "");
                } catch (InterruptedException e) {
                    
                } finally {
                    lock.unlock();
                }
                return true;
                
            }
            void add(int val) {
                lock.lock();
                try {
                    money += val;
                    System.out.println(getNowTime() + " 转入" + val + "");
                    signal.signalAll(); // 唤醒
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }
    }
    减钱加钱

    我的方法是:

    1、用synchronized

    2、try的finally语句是必须进行的

  • 相关阅读:
    drf中APIView源码分析
    将orm中模型类对象转化为字典,简单粗暴的方法
    python中uuid的使用
    每日作业 7/3
    传输文件到docker容器
    mysql 常用选项
    mysql基本语句
    mysql数据库的基本操作增删改查
    docker service的常用操作
    centos7主机重命名
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/8026486.html
Copyright © 2011-2022 走看看