精华内容
下载资源
问答
  • C++ mutex,lock_guard,unique_lock使用说明文档,详细属性介绍,简单使用介绍。
  • java 多线程加锁

    2020-06-09 16:03:32
    java 加锁方法: 1:直接加 synchronized 关键字 2:使用lock private java.util.concurrent.locks.Lock lock = new ReentrantLock(); private void fun(){ lock.lock(); try{ 执行语句...... } ...

    java 加锁方法:

    1:直接加

      synchronized 关键字

    2:使用lock

    private java.util.concurrent.locks.Lock lock = new ReentrantLock();

    private void fun(){

        lock.lock();

        try{

            执行语句......

    } finally{

        lock.unlock();

    }

    }

    例子:

    生成订单号,此处是由时间戳

    public class Tools {

    private static int count = 0;

    //单台服务器,多个线程 同时生成订单号

    public static String getNumber() {

    //区分不同的订单号

    try {

       Thread.sleep(300);

    } catch (Exception e) { // TODO: handle exception

    }

       SimpleDateFormat simpt = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");

       return simpt.format(new Date()) + "-" + ++count; //时间戳后面加了 count

    }

    }

    开启100个线程调用之:

    public class ordersService implements Runnable {
    
        private Tools orderNumGenerator  = new Tools(); //定义成全局
        public void run(){
            getNumber();
        }
        public synchronized void  getNumber(){
                String number=orderNumGenerator.getNumber();
                System.out.println(Thread.currentThread().getName()+"num"+number);
        }
        public static  void  main(String[] args){
            ordersService ordersService=new ordersService();
           for (int i=0;i<100;i++){
               new Thread(ordersService).start();
           }
        }
    }

    结果:

     多个线程共享区同一个全局变量,线程安全问题

     解决方法就是加锁

    一:使用关键字加锁

     

    或者使用 lock锁也可以

    展开全文
  • 本文实例讲述了Python多线程编程之多线程加锁操作。分享给大家供大家参考,具体如下: Python语言本身是支持多线程的,不像PHP语言。 下面的例子是多个线程做同一批任务,任务总是有task_num个,每次线程做一个任务...
  • 线程加锁

    千次阅读 2018-06-10 20:52:40
    线程加锁 在多线程加锁的过程中,要注意如下两个核心关键点: 加锁的位置,加锁的位置代表了一旦其中某一线程获取锁后,其他线程就会阻塞到此位置,当加锁的线程执行完毕释放锁后,其他线程会根据阻塞时的位置...


    1. 多线程加锁

    在多线程加锁的过程中,要注意如下两个核心关键点:

    • 加锁的位置,加锁的位置代表了一旦其中某一线程获取锁后,其他线程就会阻塞到此位置,当加锁的线程执行完毕释放锁后,其他线程会根据阻塞时的位置继续向向执行。
    • 加锁边界处理, 在到达边界时,一旦某一线程完成任务后,其他阻塞的线程就不能继续完成任务,要考虑其他线程要退出任务。
    • 防止死锁,正常情况下cpu执行一个锁要从加锁到释放锁这么一个原子性操作,若在加锁后还为解锁时,就退出任务,此时就变为死锁,自己和其他都一致会阻塞
      举例说明:
    import time
    from threading import Thread,Lock,currentThread
    import logging
    
    FORMAT = "%(asctime)s %(threadName)s %(thread)d %(message)s"
    # logging.basicConfig(format=FORMAT,level=logging.INFO)
    logging.basicConfig(format=FORMAT,level=logging.INFO)
    
    cups = []
    lock = Lock()
    def worker(count=10):
        logging.info("I'am working for CPU.")
        flag = False
        while not flag:
            #如果len(cups)=999,线程1进入循环在此枷锁,
            # 其他线程也进入此循环阻塞到此位置,若线程1执行完后,其他线程
            #也要枪锁,因此要判断是否要cups.append(1),若已经达到1000,则跳过;
            lock.acquire()
            time.sleep(0.001)
            print(len(cups))
            if len(cups) >= 1000:
                flag = True
                #若此位置加break,尚未解锁就结束,形成死锁
                #break
            #达到100时,阻塞的线程进来后,要根据flag值判断是否在添加,若没有
            #判断时,其他阻塞的线程进来依然会添加,因此会有错误
            #cups.append(1)
            #正确做法
            if not flag:
                cups.append(1)
            print(currentThread())
            lock.release()
        logging.info('I finished. cups = {}'.format(len(cups)))
    
    for _ in range(10):
        Thread(target=worker,args=(1000,)).start()

    2. 加锁类LOCK

    acquire(blocking=Ture,timeout=-1)

    • 默认情况下是阻塞状态,当无法获取到锁时,会一直处于阻塞状态,当然也可以设置timeout超时时间,到达超时时间立马退出
    • 若blocking=False时,当没有获取到锁时,立马退出,无须阻塞等待

    release

    • 释放锁,可以从任何线程调用释放
    • 已上锁的锁,会被重置为unlocked未上锁的锁上调用,抛出RuntimeError异常

    3. 加锁作用

    在多线程中,多线程同时处理一个公共变量时,线程A和线程B,如
    当x = 0, x = x + 1时,尚未执行完成,切换另外一个线程x = x +1,本来应该是2,但是因为第一个线程x= x+ 1执行一半,因此x再次变为1

    import threading
    from threading import Thread,Lock
    import time
    
    class Counter:
        def __init__(self):
            self._val = 0
    
        @property
        def value(self):
            return self._val
    
        def inc(self):
            self._val += 1
    
        def dec(self):
            self._val -= 1
    
    def run(c,count=100):
        for _ in range(count):
            for i in range(-50,50):
                if i < 0:
                    c.dec()
                else:
                    c.inc()
    
    c = Counter()
    c1 = 100
    c2 = 100
    for i in range(c1):
        Thread(target=run,args=(c,c2)).start()
    print(c.value)

    4. 可重入锁RLock

    可重入锁当线程A中获取一次或多次锁lock,同时将同一把锁lock传递到另外一个线程B中,当线程A中不释放这把锁时,线程B中就因为这把锁无法使用,线程B就处于阻塞状态。
    如:你拿一把锁链,把自行车多次上锁,但是你又想把这把锁锁另外一个自行车,肯定无法使用,因为锁还没有解开,所以另外一个自行车只能处于等待状态。

    import threading
    import time
    
    lock = threading.RLock()
    lock.acquire()
    def worker(lock):
        print("blocking ...")
        lock.acquire()
        print(threading.current_thread().ident)
        print()
        print("end blocking ...")
    
    t = threading.Thread(target=worker,args=(lock,))
    t.start()
    print(lock)
    t.join()
    print("end")
    #运行结果
    blocking ...
    <locked _thread.RLock object owner=8724 count=1 at 0x000001941A851C88>
    ##阻塞状态

    5. condion

    condion是条件通知机制,主要解决的问题是:生产者和消防者速度不匹配的问题,有了condion后,生产者生产完后,通知消费者来消费,这样更加高效的完成任务

    展开全文
  • } //多线程安全问题:一段代码,单线程执行和多线程执行结果不一致,就表明有线程安全问题 //加lock 就能解决线程安全问题--就是单线程化 --LOCK 就是保证方法块任意时刻只有一个线程能进去,其他线程就排队 //Lock...
            private void button8_Click(object sender, EventArgs e)
            {
                //for (int i = 0; i < 5; i++)
                //{
                //    int k = i;
                //    Thread.Sleep(5);
                //    Task.Run(() =>
                //    {
                //        Console.WriteLine($"This is i={i} k={k} Start {Thread.CurrentThread.ManagedThreadId}");
                //        Thread.Sleep(200);
                //        Console.WriteLine($"This is i={i} k={k} End>>>>> {Thread.CurrentThread.ManagedThreadId}");
                //    });
                //}
    
                List<int> intList = new List<int>();
                for (int i = 0; i < 10000; i++)
                {
                    Task.Run(() =>//多线程之后,结果变成小于10000,有数据丢失了
                    {
                       // Monitor.Enter(LOCK); 和lock原理一样
                        lock(LOCK)
                        {
                            intList.Add(i);
                        }
                       // Monitor.Exit(LOCK);
                    });
                }
                //多线程安全问题:一段代码,单线程执行和多线程执行结果不一致,就表明有线程安全问题
    
                //加lock 就能解决线程安全问题--就是单线程化 --LOCK 就是保证方法块任意时刻只有一个线程能进去,其他线程就排队
                //Lock原理 -- 语法糖 --等于Monitor ---锁定一个内存引用地址 ---所以不能是值类型 -- 也不能是null 
                Thread.Sleep(5000);
                Console.WriteLine(intList.Count);
            }
    
            //private 防止外面访问, static 唯一只有一个 readonly 避免地址被修改 引用失效影响锁
            private static readonly object LOCK = new object();
    
    展开全文
  • 1.多线程加锁代码---为神经网络中的全连接做准备工作,练手 #include <iostream> #include <thread> #include <string> #include <mutex>//互斥锁 /* 1.Mutex 系列类(四种)...

    1.多线程加锁代码---为神经网络中的全连接做准备工作,练手

    #include <iostream>
    #include <thread>
    #include <string>
    #include <mutex>//互斥锁
    /*
    1.Mutex 系列类(四种)(https://www.cnblogs.com/haippy/p/3237213.html)
    	std::mutex,最基本的 Mutex 类。
    	std::recursive_mutex,递归 Mutex 类。
    	std::time_mutex,定时 Mutex 类。
    	std::recursive_timed_mutex,定时递归 Mutex 类
    2.volatile是一个特征修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,
        且要求每次直接读值。
    3.std::mutex 的成员函数
    	构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。
    
    	lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:
    		(1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。
    		(2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
    		(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
    
    	unlock(), 解锁,释放对互斥量的所有权。
    
    	try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面3 种情况,
    		(1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。
    		(2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。
    		(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
    4.std是一个命名空间(namespace),‘::’是作用域运算符,cout是std空间中的一个函数名。使用cout时,必须有使用std命名空间的说明,有两种说明方式。
    
    	方式一:每次使用时对cout说明:       
    			std::cout << "Input two numbers:";
    	方式二:在主函数前说明一下,后面就可以直接使用cout:
    			using namespace std;
    			cout << "Input two numbers:";
    5.td::this_thread::yield: 当前线程放弃执行,操作系统调度另一线程继续执行。即当前线程将未使用完的“CPU时间片”让给其他线程使用,等其他线程使用完后再与其他线程一起竞争"CPU"。
      std::this_thread::sleep_for: 表示当前线程休眠一段时间,休眠期间不与其他线程竞争CPU,根据线程需求,等待若干时间。
    
    6.
    */
    // 车票总数是100张
    volatile int tickets = 100;//
    // 全局的互斥锁
    std::mutex mtx;
    
    // 线程函数
    void sellTicketTask(std::string wndName)
    {
    	while (tickets > 0)
    	{
    		// 获取互斥锁资源
    		mtx.lock();
    		if (tickets > 0)
    		{
    			std::cout << wndName << " 售卖第" << tickets << "张票" << std::endl;
    			tickets--;
    		}
    		// 释放互斥锁资源
    		mtx.unlock();
    
    		// 每卖出一张票,睡眠100ms,让每个窗口都有机会卖票
    		std::this_thread::sleep_for(std::chrono::milliseconds(100));//std::this_thread::sleep_for表示当前线程休眠一段时间,休眠期间不与其他线程竞争CPU,根据线程需求,等待若干时间。
    	}
    }
    
    // 模拟车站窗口卖票,使用C++11 线程互斥锁mutex
    int main()
    {
    	// 创建三个模拟窗口卖票线程
    	std::thread t1(sellTicketTask, "车票窗口一");
    	std::thread t2(sellTicketTask, "车票窗口二");
    	std::thread t3(sellTicketTask, "车票窗口三");
    
    	// 等待三个线程执行完成
    	t1.join();
    	t2.join();
    	t3.join();
    
    	return 0;
    }
    

     

    2.自己又写了一个

    #include <windows.h>
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <string>
    
    using namespace std;//使用标准命名空间:(https://baike.baidu.com/item/using%20namespace%20std/10360651?fr=aladdin)
    
    //DWORD WINAPI Fun1(LPVOID lpParameter);//LPVOID这个是一个宏定义 表示的是指向空类型的指针
    
    //DWORD WINAPI Fun2(LPVOID lpParameter);
    //DWORD WINAPI Fun3(LPVOID lpParameter);
    
    // 全局的互斥锁
    std::mutex mtx;
    
    int index = 0;
    //int money = 100;
    int tickets = 100;   //全局变量tickets用来表示销售的剩余票数
    					 //线程1入口函数
    					 //DWORD WINAPI Fun1(LPVOID lpParameter)
    int Fun1(std::string wndName)
    {
    
    	while (TRUE)
    	{
    		mtx.lock();
    		if (tickets > 0)
    		{
    			cout << "车票窗口一 : " << tickets-- << endl;//表示输出换行的意思,相当于C语言里面的printf("\n");
    
    		}
    		else
    		{
    			break;
    		}
    		mtx.unlock();
    		Sleep(1);
    
    	}
    	return 0;
    }
    
    //线程2的入口函数
    //DWORD WINAPI Fun2(std::string wndName)
    int Fun2(std::string wndName)
    {
    	while (TRUE)
    	{
    		mtx.lock();
    		if (tickets > 0)
    		{
    			
    			cout << "车票窗口二 : " << tickets-- << endl;
    		}
    		else
    		{
    			break;
    		}
    		mtx.unlock();
    		Sleep(1);
    	}
    	return 0;
    }
    //DWORD WINAPI Fun3(std::string wndName)
    int Fun3(std::string wndName)
    {
    	while (TRUE)
    	{
    		mtx.lock();
    		if (tickets > 0)
    		{
    			
    			cout << "车票窗口三: " << tickets-- << endl;
    		}
    		else
    		{
    			break;
    		}
    		mtx.unlock();
    		Sleep(1);
    	}
    	return 0;
    }
    
    ///
    int main(int argc, TCHAR* argv[])
    {
    	/*HANDLE hThread1;//Handler:是一个消息分发对象,进行发送和处理消息
    	HANDLE hThread2;//Handler:无类型指针(不指向任何类型数据的指针)
    	HANDLE hThread3;
    					//创建线程
    	hThread1 = CreateThread(NULL,//有没有安全性描述
    		0,	//默认线程栈的大小(让新线程采用与调用线程一样的栈大小)
    		Fun1, //指定线程的入口函数地址(线程函数指针)
    		NULL,//这里就是你要传进Fun1函数的参数
    		0,// 没有附加属性
    		NULL);// 不需要获得线程id,线程创建标记,0表示让线程一旦创立就运行、新线程的ID,不需要的话为null
    
    
    	hThread2 = CreateThread(NULL, 0, Fun2, NULL, 0, NULL);
    	hThread3 = CreateThread(NULL, 0, Fun3, NULL, 0, NULL);
    
    	CloseHandle(hThread1);  //调用CloseHandle将此线程的句柄关闭,关闭句柄时,系统会递减该线程内核对象的使用计数。
    	CloseHandle(hThread2);
    	CloseHandle(hThread3);
    
    	Sleep(4000); //让线程暂停运行4s
    	system("pause");
    	return 0;
    	*/
    
    	std::thread t1(Fun1, "车票窗口一");
    	std::thread t2(Fun2, "车票窗口二");
    	std::thread t3(Fun3, "车票窗口三");
    
    	t1.join();
    	t2.join();
    	t3.join();
    
    	return 0;
    
    }
    
    

     

    展开全文
  • 线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏。 二、锁的原理 Java中每个对象都有一个内置锁。 当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this...
  • python-线程加锁

    千次阅读 2019-06-06 14:05:18
    刚开始学习python,之前c++ c# 中,线程加锁尤为重要,当前看到一个博文,学习下。 python 提供的多线程模型中并没有提供读写锁,读写锁相对于单纯的互斥锁,适用性更高,可以多个线程同时占用读模式的读写锁,但是...
  • 关于多线程加锁问题

    千次阅读 2018-08-31 09:24:48
    偶然间翻到了多线程加锁的帖子,记录一下 多线程间共享变量加不加锁取决于变量类型以及大小,跟CPU单次操作有关。 从:https://blog.csdn.net/youtherzhang/article/details/76093570 大神的测试结果来看(感谢...
  • Java 多线程加锁的方式

    万次阅读 2018-07-20 09:42:47
    一.Java多线程可以通过: 1. synchronized关键字 2. Java.util.concurrent包中的lock接口和ReentrantLock实现类 这两种方式实现加锁。   二.synchronized关键字加锁的缺陷:   如果一个代码块被synchro...
  • 不管是Java还是C,都会遇到多线程数据同步的问题。一种解决数据因为多线程访问导致出错的方案就是使用锁。 通过Java的字节码或者C程序的汇编指令看,我们编写的语句,都是由多个机器指令完成的,所以会出现多个线程...
  • Windows下多线程加锁

    2019-03-27 16:04:51
    同时,获取锁和释放锁的线程必须是同一个线程。常用的互斥锁操作有  CreateMutex  OpenMutex  ReleaseMutex  那么,怎么用互斥锁进行数据的访问呢,其实不难。  WaitForSingleObject(/*...*/);  do_...
  • python3线程加锁的一个例子

    千次阅读 2019-06-08 16:47:35
    再这个例子中,线程加上锁之后有并行变成了实际上的串行 [root@linux1 python_tidb]# cat mypy02.py #!/usr/bin/env python3 import pymysql,sys,os import _thread,time def counter(myid,count): mutex.acquire...
  • c++线程加锁

    2013-01-13 12:29:35
    代码中的临界区变量(cs)就可以看作是变量s的锁,当函数EnterCriticalSection返回时,当前线程就获得了这把锁,之后就是对变量的访问了。访问完成后,调用LeaveCriticalSection表示释放这把锁,允许其他线程继续...
  • Java线程加锁的三种方式

    千次阅读 2018-12-03 15:00:11
    当A线程访问一个object的时候,首先会获取该对象的对象锁,然后访问锁定的代码,而B线程访问一个对象object多顶的代码区时,因为线程A之前获取到对象object的对象锁,因此线程B访问同步代码区的时候会被阻塞,直到...
  • 1.多线程加锁 #include <mutex> mutex mut; mut.lock (); mut.unlock (); 以下代码执行结果为200000000,证明没有发生val被一个线程获取处理还没写回的时候,被另一个线程读走。 如果不加锁,val的结果会...
  • 1、线程开启 Qt中,开启子线程,一般有两种方法: a, 定义工作类worker: worker继承 QThread, 重写run函数,在主线程中实例化worker,把耗时工作放进worker的run函数中完成,结束后,往主线程中发信号,传递参数即可...
  • 线程加锁-----Unity c#

    2019-11-12 10:19:47
    private System.Object sendLck; sendLck = new System.Object(); lock (sendLck) { //加锁代码 }
  • 主要介绍了java多线程加锁以及Condition类的使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • Android 多线程加锁

    千次阅读 2017-04-20 17:04:32
    两个线程同一把锁,防止读取得数据不完整 取得时候加锁 确保数据取完,读的时候使用通一把锁确保数据读完 private Lock lock = new ReentrantLock(); // 软解 本地回调方法  // @{link startThreads()} ...
  • VC++多线程加锁封装(附源码)

    多人点赞 热门讨论 2020-09-30 10:31:57
    源代码demo已上传到百度网盘:永久生效 ,代码封装了 线程函数读、写 加锁功能,支持跨平台,绝对好用 直接上代码看封装类的头文件 #ifndef __CLOCKX__ #define __CLOCKX__ #ifdef WIN32 #include <Windows.h...
  • c++线程加锁.pdf

    2021-10-06 17:15:22
    c++线程加锁.pdf
  • 在一个线程加锁,另一个线程解锁

    千次阅读 2017-08-03 15:03:30
    一般来讲,一个线程加锁,另一个线程解锁,是很容易死锁的。 产生死锁的四个必要条件: (1) 互斥条件:一个资源每次只能被一个进程使用。 (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持...
  • Java 多线程加锁的方式总结及对比

    万次阅读 多人点赞 2017-03-28 14:27:53
    一.Java多线程可以通过: 1. synchronized关键字 2. Java.util.concurrent包中的lock接口和ReentrantLock实现类 这两种方式实现加锁。 二.synchronized关键字加锁的缺陷: 如果一个代码块被s
  • python 多线程的使用多线程主要用于大量的IO操作时的并发执行,以此来提高效率!多进程主要用于大量的计算,进而充分发挥CPU的性能!这里主要讲述两种多线程的使用:threading.Threadconcurrent.futures....
  • 单线程多路复用和多线程加锁的区别 unix   linux   c   golang   Deen  2015年11月21日提问 关注  9  关注 收藏  1  收藏, 776  浏览 问题对人有帮助,内容...
  • 以下是我的测试对象加锁的代码,但是对运行出来的结果不太理解 public class Test0 implements Runnable { int b = 100; public synchronized void m1() throws Exception { b = 1000; System.out.println(b+...
  • 线程 加锁的三种方式

    千次阅读 2017-03-20 09:45:49
    加锁的第一种方式: public class RootBeanDefinition{ final Object constructorArgumentLock = new Object(); final Object postProcessingLock = new Object(); public void ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 241,380
精华内容 96,552
关键字:

线程加锁