Synchronization of functions

I want my two functions in same file (let’s say active and passive) to run at the same time.
How can I do this?

There are multiple ways to accomplish this, depending on what you are trying to accomplish:

We would need more information about what problem you are trying to solve to give you more information than that.

1 Like

Sounds like you’re starting a server and a client in the same program? If so, look into the asyncio module, which will let you have two async functions that run in parallel.

1 Like

@TomRitchford @Rosuav
I’m just creating clicker with a passive income…

import time

money = 0
click = 1
passive_click = 0

def passive():
  global money
  money += passive_click
  time.sleep(1)

def shop():
  global click
  print('"l" для выхода')
  print('------------ Магазин -----------')
  print('1. +1 за клик           10$')
  print('2. +5 за клик           50$')
  print('3. Х2 за клик           100$')
  print('4. +1 пассивный доход   80$')
  print('--------------------------------')
  while True:
    global money
    b = input()
    if b == "l":
      break
    elif b == "1":
      if money >= 10:
        click += 1
        money -= 10
      else:
        print("Недостаточно денег")
    elif b == "2":
      if money >= 50:
        click += 5
        money -= 50
      else:
        print("Недостаточно денег")
    elif b == "3":
      if money >= 100:
        click *= 2
        money -= 100
      else:
        print("Недостаточно денег")
    elif b == "4":
      if money >= 80:
        click += 1
        money -= 80
      else:
        print("Недостаточно денег")
    print(money)

print('Нажмите любую клавишу для заработка денег')
print('"q" для выхода, "s" для магазина')
while True:
  a = input()
  if a == "q":
    print(f'Итого: {money}$')
    break
  elif a == "s":
    shop()
  else:
    money += click
  print(f'Баланс: {money}$')

Thanks for the code sample, it makes it all clear!

You probably want to do this with threading.

Explaining how this all works is beyond the scope of this page; you should find a tutorial on Python threading that you like.

And beware - you have a whole bunch of “race conditions”.

In the example code, imagine that the statement

money += passive_click

happens at the same time as the other statement

money -= 10

One of those two calculations could be lost. And if you do this computation enough, it’s pretty well certain that this will happen.

You’re going to need “locking” to make it all work correctly.

I think this is a really good exercise to learn how threading and locking works, because it’s simple enough, but really does need multiple threads.

Have fun with it! :slightly_smiling_face:

1 Like

Thank you, I will try my best.

Oh! Then I completely misjudged the intent - but the idea is still the same. You can do it with threads, as Tom suggested; I would also still recommend looking into asyncio, as this makes a lot of things easier for this sort of simple case.

One neat thing about Python’s concurrency options is that they will largely end up looking similar. You can write your code with asyncio, and then in the future, change to threading. Or you can write with threading, and then in the future, change to asyncio (although that’s a little harder in some situations, but in your case, it’d be fairly straight-forward). So don’t stress too much about how you do this, and maybe even consider dabbling in multiple patterns to see which one you want to use for the final project.

1 Like

@Rosuav @TomRitchford
I did it!:heart:
Can you check my code for possible problems in the future?

Clicker's code
import time
import threading

money = 0
click = 1
passive_click = 0
cooldown = 15
stop = False

def passive():
  global money, cooldown
  while True:
    if stop == False and passive_click > 0:
      print(f'+{passive_click}$')
      money += passive_click
    time.sleep(cooldown/10)

my_thread = threading.Thread(target=passive, name='passive_income')

def shop():
  global stop, click, money, passive_click, cooldown
  stop = True
  print(stop)
  print('"l" для выхода')
  print(f'---------- Магазин --------- {money}$')
  print('1. +1 за клик           10$')
  print('2. +5 за клик           50$')
  print('3. Х2 за клик           100$')
  print('4. +50  за клик         600$')
  print('5. +100  за клик        1000$')
  print('6. +1 пассивный доход   80$')
  print('7. +5 пассивный доход   400$')
  print('8. +15 пассивный доход  1000$')
  print('9. +50 пассивный доход  3000$')
  print('10. -0.1 секунда кд      150$')
  print('-----------------------------')
  while True:
    b = input()
    if b == "l":
      stop = False
      break
    elif b == "1":
      if money >= 10:
        click += 1
        money -= 10
      else:
        print("Недостаточно денег")
    elif b == "2":
      if money >= 50:
        click += 5
        money -= 50
      else:
        print("Недостаточно денег")
    elif b == "3":
      if money >= 100:
        click *= 2
        money -= 100
      else:
        print("Недостаточно денег")
    elif b == "4":
      if money >= 600:
        click += 50
        money -= 600
      else:
        print("Недостаточно денег")
    elif b == "5":
      if money >= 1000:
        click += 100
        money -= 1000
      else:
        print("Недостаточно денег")
    elif b == "6":
      if money >= 80:
        passive_click += 1
        money -= 80
      else:
        print("Недостаточно денег")
    elif b == "7":
      if money >= 400:
        passive_click += 5
        money -= 400
      else:
        print("Недостаточно денег")
    elif b == "8":
      if money >= 1000:
        passive_click += 15
        money -= 1000
      else:
        print("Недостаточно денег")
    elif b == "9":
      if money >= 3000:
        passive_click += 50
        money -= 3000
      else:
        print("Недостаточно денег")
    elif b == "10":
      if money >= 150 and cooldown > 1:
        cooldown -= 1
        money -= 150
      else:
        print("Недостаточно денег")
    print(f'Осталось: {money}$, Кликов: {click}, Пассивный доход: {passive_click}$/{cooldown / 10} сек')

print('Нажмите любую клавишу для заработка денег')
print('"q" для выхода, "s" для магазина')
my_thread.start()

while True:
  a = input()
  if a == "q":
    stop = True
    print(f'Итого: {money}$, Кликов: {click}, Пассивный доход: {passive_click}$/{cooldown / 10} сек')
    break
  elif a == "s":
    shop()
  else:
    money += click
  print(f'Баланс: {money}$')

Looks decent! Have a try at doing this asynchronously, too, but this should be fine too.

Good as far as it goes, but you still need to lock your “critical sections”, or you’re going to get these race conditions! :slightly_smiling_face:

Let me show you what to do so you get the idea.

stop = False
lock = threading.Lock()

def passive():
  global money, cooldown
  while not stop:
    with lock:
      if passive_click > 0:
        print(f'+{passive_click}$')
        money += passive_click
    time.sleep(cooldown/10)  # The sleep must be outside the lock!!

Then later on:

    elif b == "1":
      with lock:
        if money >= 10:
          click += 1
          money -= 10
        else:

You’ll need to add a lot of locks, one for every time you use the variables money or click. :slight_smile:

Which is a reason to consider single-threaded asynchronicity :slight_smile:

1 Like

Yes, I did contemplate that, but ultimately, I decided that teaching threading and locks would be easier and more useful for a beginner who’s going to be reading a lot of other code.